Spaces:
Sleeping
Sleeping
| const asyncHandler = require('express-async-handler'); | |
| const PromptGroup = require('../models/PromptGroup'); | |
| const logger = require('../utils/logger'); | |
| // @desc 获取所有提示词组 | |
| // @route GET /api/prompt-groups | |
| // @access Private | |
| const getPromptGroups = asyncHandler(async (req, res) => { | |
| const promptGroups = await PromptGroup.find({}) | |
| .populate('category', 'name color') | |
| .sort({ updatedAt: -1 }); | |
| res.json(promptGroups); | |
| }); | |
| // @desc 获取单个提示词组 | |
| // @route GET /api/prompt-groups/:id | |
| // @access Private | |
| const getPromptGroupById = asyncHandler(async (req, res) => { | |
| const promptGroup = await PromptGroup.findById(req.params.id) | |
| .populate('category', 'name color'); | |
| if (promptGroup) { | |
| res.json(promptGroup); | |
| } else { | |
| res.status(404); | |
| throw new Error('提示词组未找到'); | |
| } | |
| }); | |
| // @desc 创建提示词组 | |
| // @route POST /api/prompt-groups | |
| // @access Private | |
| const createPromptGroup = asyncHandler(async (req, res) => { | |
| const { name, description, category } = req.body; | |
| const promptGroup = await PromptGroup.create({ | |
| name, | |
| description, | |
| category, | |
| prompts: [], | |
| workflows: [], | |
| dslFiles: [], | |
| createdBy: req.user._id, | |
| }); | |
| if (promptGroup) { | |
| res.status(201).json(promptGroup); | |
| } else { | |
| res.status(400); | |
| throw new Error('无效的提示词组数据'); | |
| } | |
| }); | |
| // @desc 更新提示词组 | |
| // @route PUT /api/prompt-groups/:id | |
| // @access Private | |
| const updatePromptGroup = asyncHandler(async (req, res) => { | |
| const { name, description, category } = req.body; | |
| const promptGroup = await PromptGroup.findById(req.params.id); | |
| if (promptGroup) { | |
| promptGroup.name = name || promptGroup.name; | |
| promptGroup.description = description || promptGroup.description; | |
| promptGroup.category = category || promptGroup.category; | |
| const updatedPromptGroup = await promptGroup.save(); | |
| res.json(updatedPromptGroup); | |
| } else { | |
| res.status(404); | |
| throw new Error('提示词组未找到'); | |
| } | |
| }); | |
| // @desc 删除提示词组 | |
| // @route DELETE /api/prompt-groups/:id | |
| // @access Private | |
| const deletePromptGroup = asyncHandler(async (req, res) => { | |
| const promptGroup = await PromptGroup.findById(req.params.id); | |
| if (promptGroup) { | |
| await promptGroup.deleteOne(); | |
| res.json({ message: '提示词组已删除' }); | |
| } else { | |
| res.status(404); | |
| throw new Error('提示词组未找到'); | |
| } | |
| }); | |
| // @desc 添加提示词到提示词组 | |
| // @route POST /api/prompt-groups/:id/prompts | |
| // @access Private | |
| const addPromptToGroup = asyncHandler(async (req, res) => { | |
| const { title, content, tags } = req.body; | |
| const promptGroup = await PromptGroup.findById(req.params.id); | |
| if (promptGroup) { | |
| const newPrompt = { | |
| title, | |
| content, | |
| tags: tags || [], | |
| createdAt: new Date(), | |
| updatedAt: new Date(), | |
| }; | |
| promptGroup.prompts.push(newPrompt); | |
| promptGroup.updatedAt = new Date(); | |
| const updatedPromptGroup = await promptGroup.save(); | |
| res.status(201).json(updatedPromptGroup.prompts[updatedPromptGroup.prompts.length - 1]); | |
| } else { | |
| res.status(404); | |
| throw new Error('提示词组未找到'); | |
| } | |
| }); | |
| // @desc 更新提示词 | |
| // @route PUT /api/prompt-groups/:id/prompts/:promptId | |
| // @access Private | |
| const updatePrompt = asyncHandler(async (req, res) => { | |
| const { title, content, tags } = req.body; | |
| const promptGroup = await PromptGroup.findById(req.params.id); | |
| if (promptGroup) { | |
| const promptIndex = promptGroup.prompts.findIndex( | |
| (p) => p._id.toString() === req.params.promptId | |
| ); | |
| if (promptIndex !== -1) { | |
| promptGroup.prompts[promptIndex].title = title || promptGroup.prompts[promptIndex].title; | |
| promptGroup.prompts[promptIndex].content = content || promptGroup.prompts[promptIndex].content; | |
| promptGroup.prompts[promptIndex].tags = tags || promptGroup.prompts[promptIndex].tags; | |
| promptGroup.prompts[promptIndex].updatedAt = new Date(); | |
| promptGroup.updatedAt = new Date(); | |
| const updatedPromptGroup = await promptGroup.save(); | |
| res.json(updatedPromptGroup.prompts[promptIndex]); | |
| } else { | |
| res.status(404); | |
| throw new Error('提示词未找到'); | |
| } | |
| } else { | |
| res.status(404); | |
| throw new Error('提示词组未找到'); | |
| } | |
| }); | |
| // @desc 删除提示词 | |
| // @route DELETE /api/prompt-groups/:id/prompts/:promptId | |
| // @access Private | |
| const deletePrompt = asyncHandler(async (req, res) => { | |
| const promptGroup = await PromptGroup.findById(req.params.id); | |
| if (promptGroup) { | |
| const promptExists = promptGroup.prompts.some( | |
| (p) => p._id.toString() === req.params.promptId | |
| ); | |
| if (promptExists) { | |
| promptGroup.prompts = promptGroup.prompts.filter( | |
| (p) => p._id.toString() !== req.params.promptId | |
| ); | |
| promptGroup.updatedAt = new Date(); | |
| await promptGroup.save(); | |
| res.json({ message: '提示词已删除' }); | |
| } else { | |
| res.status(404); | |
| throw new Error('提示词未找到'); | |
| } | |
| } else { | |
| res.status(404); | |
| throw new Error('提示词组未找到'); | |
| } | |
| }); | |
| // @desc 添加DSL文件到提示词组 - 修改为支持文本内容 | |
| // @route POST /api/prompt-groups/:id/dsl-files | |
| // @access Private | |
| const addDslFileToGroup = asyncHandler(async (req, res) => { | |
| try { | |
| const { name, content, fileData, mimeType } = req.body; | |
| logger.info(`正在添加DSL文件: ${name}`); | |
| // 验证请求数据 | |
| if (!name) { | |
| res.status(400); | |
| throw new Error('文件名是必需的'); | |
| } | |
| // 确保至少提供了文本内容或文件数据中的一个 | |
| if (!content && !fileData) { | |
| res.status(400); | |
| throw new Error('请提供YAML内容或上传文件'); | |
| } | |
| const promptGroup = await PromptGroup.findById(req.params.id); | |
| if (!promptGroup) { | |
| res.status(404); | |
| throw new Error('提示词组未找到'); | |
| } | |
| // 确保文件名以 .yml 结尾 | |
| let fileName = name; | |
| if (!fileName.toLowerCase().endsWith('.yml')) { | |
| fileName = fileName.replace(/\.[^/.]+$/, '') + '.yml'; | |
| } | |
| // 处理内容: 优先使用提供的内容,如果没有则尝试解码文件数据 | |
| let yamlContent = content; | |
| // 如果提供了fileData但没有提供content,尝试将fileData转换为文本 | |
| if (!yamlContent && fileData) { | |
| try { | |
| // 尝试将Base64解码为文本 | |
| const buffer = Buffer.from(fileData, 'base64'); | |
| yamlContent = buffer.toString('utf-8'); | |
| logger.info(`成功从文件数据提取YAML内容`); | |
| } catch (error) { | |
| logger.error(`从文件数据提取内容失败: ${error.message}`); | |
| res.status(400); | |
| throw new Error('无法从上传的文件中提取内容'); | |
| } | |
| } | |
| const newDslFile = { | |
| name: fileName, | |
| content: yamlContent, | |
| mimeType: mimeType || 'application/x-yaml', | |
| uploadedAt: new Date(), | |
| }; | |
| promptGroup.dslFiles.push(newDslFile); | |
| promptGroup.updatedAt = new Date(); | |
| const updatedPromptGroup = await promptGroup.save(); | |
| logger.info(`DSL文件添加成功: ${fileName}`); | |
| res.status(201).json(updatedPromptGroup.dslFiles[updatedPromptGroup.dslFiles.length - 1]); | |
| } catch (error) { | |
| logger.error(`添加DSL文件时出错: ${error.message}`); | |
| if (!res.statusCode || res.statusCode === 200) { | |
| res.status(500); | |
| } | |
| throw error; | |
| } | |
| }); | |
| // @desc 更新DSL文件 | |
| // @route PUT /api/prompt-groups/:id/dsl-files/:fileId | |
| // @access Private | |
| const updateDslFile = asyncHandler(async (req, res) => { | |
| try { | |
| const { name, content } = req.body; | |
| if (!name && !content) { | |
| res.status(400); | |
| throw new Error('请提供要更新的文件名或内容'); | |
| } | |
| const promptGroup = await PromptGroup.findById(req.params.id); | |
| if (!promptGroup) { | |
| res.status(404); | |
| throw new Error('提示词组未找到'); | |
| } | |
| const fileIndex = promptGroup.dslFiles.findIndex( | |
| file => file._id.toString() === req.params.fileId | |
| ); | |
| if (fileIndex === -1) { | |
| res.status(404); | |
| throw new Error('DSL文件未找到'); | |
| } | |
| // 更新文件名 - 确保以.yml结尾 | |
| if (name) { | |
| let updatedName = name; | |
| if (!updatedName.toLowerCase().endsWith('.yml')) { | |
| updatedName = updatedName.replace(/\.[^/.]+$/, '') + '.yml'; | |
| } | |
| promptGroup.dslFiles[fileIndex].name = updatedName; | |
| } | |
| // 更新内容 | |
| if (content) { | |
| promptGroup.dslFiles[fileIndex].content = content; | |
| } | |
| // 更新时间戳 | |
| promptGroup.dslFiles[fileIndex].uploadedAt = new Date(); | |
| promptGroup.updatedAt = new Date(); | |
| const updatedPromptGroup = await promptGroup.save(); | |
| logger.info(`DSL文件更新成功: ${promptGroup.dslFiles[fileIndex].name}`); | |
| res.status(200).json(updatedPromptGroup.dslFiles[fileIndex]); | |
| } catch (error) { | |
| logger.error(`更新DSL文件时出错: ${error.message}`); | |
| if (!res.statusCode || res.statusCode === 200) { | |
| res.status(500); | |
| } | |
| throw error; | |
| } | |
| }); | |
| // @desc 删除DSL文件 | |
| // @route DELETE /api/prompt-groups/:id/dsl-files/:fileId | |
| // @access Private | |
| const deleteDslFile = asyncHandler(async (req, res) => { | |
| const promptGroup = await PromptGroup.findById(req.params.id); | |
| if (promptGroup) { | |
| const fileExists = promptGroup.dslFiles.some( | |
| (f) => f._id.toString() === req.params.fileId | |
| ); | |
| if (fileExists) { | |
| promptGroup.dslFiles = promptGroup.dslFiles.filter( | |
| (f) => f._id.toString() !== req.params.fileId | |
| ); | |
| promptGroup.updatedAt = new Date(); | |
| await promptGroup.save(); | |
| res.json({ message: 'DSL文件已删除' }); | |
| } else { | |
| res.status(404); | |
| throw new Error('DSL文件未找到'); | |
| } | |
| } else { | |
| res.status(404); | |
| throw new Error('提示词组未找到'); | |
| } | |
| }); | |
| module.exports = { | |
| getPromptGroups, | |
| getPromptGroupById, | |
| createPromptGroup, | |
| updatePromptGroup, | |
| deletePromptGroup, | |
| addPromptToGroup, | |
| updatePrompt, | |
| deletePrompt, | |
| addDslFileToGroup, | |
| updateDslFile, | |
| deleteDslFile, | |
| }; |