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, | |
}; |