feat(admin): Complete Phase 3.5.1-3.5.4 Prompt Management System (83%)

Summary:
- Implement Prompt management infrastructure and core services
- Build admin portal frontend with light theme
- Integrate CodeMirror 6 editor for non-technical users

Phase 3.5.1: Infrastructure Setup
- Create capability_schema for Prompt storage
- Add prompt_templates and prompt_versions tables
- Add prompt:view/edit/debug/publish permissions
- Migrate RVW prompts to database (RVW_EDITORIAL, RVW_METHODOLOGY)

Phase 3.5.2: PromptService Core
- Implement gray preview logic (DRAFT for debuggers, ACTIVE for users)
- Module-level debug control (setDebugMode)
- Handlebars template rendering
- Variable extraction and validation (extractVariables, validateVariables)
- Three-level disaster recovery (database -> cache -> hardcoded fallback)

Phase 3.5.3: Management API
- 8 RESTful endpoints (/api/admin/prompts/*)
- Permission control (PROMPT_ENGINEER can edit, SUPER_ADMIN can publish)

Phase 3.5.4: Frontend Management UI
- Build admin portal architecture (AdminLayout, OrgLayout)
- Add route system (/admin/*, /org/*)
- Implement PromptListPage (filter, search, debug switch)
- Implement PromptEditor (CodeMirror 6 simplified for clinical users)
- Implement PromptEditorPage (edit, save, publish, test, version history)

Technical Details:
- Backend: 6 files, ~2044 lines (prompt.service.ts 596 lines)
- Frontend: 9 files, ~1735 lines (PromptEditorPage.tsx 399 lines)
- CodeMirror 6: Line numbers, auto-wrap, variable highlight, search, undo/redo
- Chinese-friendly: 15px font, 1.8 line-height, system fonts

Next Step: Phase 3.5.5 - Integrate RVW module with PromptService

Tested: Backend API tests passed (8/8), Frontend pending user testing
Status: Ready for Phase 3.5.5 RVW integration
This commit is contained in:
2026-01-11 21:25:16 +08:00
parent cdfbc9927a
commit 5523ef36ea
297 changed files with 15914 additions and 1266 deletions

View File

@@ -0,0 +1,160 @@
/**
* RVW模块 Prompt 迁移脚本
*
* 将现有文件Prompt迁移到数据库
*
* 迁移内容:
* 1. RVW_EDITORIAL - 稿约规范性评估 (review_editorial_system.txt)
* 2. RVW_METHODOLOGY - 方法学质量评估 (review_methodology_system.txt)
* 3. RVW_TOPIC_SYSTEM - 选题评估系统提示 (topic_evaluation_system.txt)
* 4. RVW_TOPIC_USER - 选题评估用户模板 (topic_evaluation_user.txt)
*/
import { PrismaClient, PromptStatus } from '@prisma/client';
import * as fs from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const prisma = new PrismaClient();
// 变量提取函数
function extractVariables(content: string): string[] {
const regex = /\{\{(\w+)\}\}/g;
const variables = new Set<string>();
let match;
while ((match = regex.exec(content)) !== null) {
// 排除 Handlebars 控制语句如 #if, /if
if (!match[1].startsWith('#') && !match[1].startsWith('/')) {
variables.add(match[1]);
}
}
return Array.from(variables);
}
// RVW Prompt 配置(只有 2 个)
// 注意topic_evaluation_* 是"选题评估"功能,不属于 RVW 审稿模块
const rvwPrompts = [
{
code: 'RVW_EDITORIAL',
name: '稿约规范性评估',
module: 'RVW',
description: '评估医学稿件是否符合期刊稿约规范包括文题、摘要、参考文献等11项标准。输出JSON格式的评分和建议。',
file: 'review_editorial_system.txt',
modelConfig: { model: 'deepseek-v3', temperature: 0.3 },
},
{
code: 'RVW_METHODOLOGY',
name: '方法学质量评估',
module: 'RVW',
description: '评估医学稿件的科研设计、统计学方法和统计分析质量共20个检查点。输出JSON格式的评分和建议。',
file: 'review_methodology_system.txt',
modelConfig: { model: 'deepseek-v3', temperature: 0.3 },
},
];
async function main() {
console.log('🚀 开始迁移 RVW Prompt 到数据库...\n');
const promptsDir = path.join(__dirname, '..', 'prompts');
for (const prompt of rvwPrompts) {
console.log(`📄 处理: ${prompt.code} (${prompt.name})`);
// 读取文件内容
const filePath = path.join(promptsDir, prompt.file);
if (!fs.existsSync(filePath)) {
console.log(` ⚠️ 文件不存在: ${filePath}`);
continue;
}
const content = fs.readFileSync(filePath, 'utf-8').trim();
const variables = extractVariables(content);
console.log(` 📝 内容长度: ${content.length} 字符`);
console.log(` 🔤 提取变量: [${variables.join(', ')}]`);
// 创建或更新模板
const template = await prisma.prompt_templates.upsert({
where: { code: prompt.code },
update: {
name: prompt.name,
description: prompt.description,
variables: variables.length > 0 ? variables : null,
updated_at: new Date(),
},
create: {
code: prompt.code,
name: prompt.name,
module: prompt.module,
description: prompt.description,
variables: variables.length > 0 ? variables : null,
},
});
// 检查是否已有 ACTIVE 版本
const existingActive = await prisma.prompt_versions.findFirst({
where: {
template_id: template.id,
status: PromptStatus.ACTIVE,
},
});
if (existingActive) {
console.log(` ✅ 已存在 ACTIVE 版本 (v${existingActive.version})`);
} else {
// 创建第一个 ACTIVE 版本
await prisma.prompt_versions.create({
data: {
template_id: template.id,
version: 1,
content: content,
model_config: prompt.modelConfig,
status: PromptStatus.ACTIVE,
changelog: '从文件迁移的初始版本',
created_by: 'system-migration',
},
});
console.log(` ✅ 创建 ACTIVE 版本 (v1)`);
}
console.log('');
}
// 验证结果
console.log('═══════════════════════════════════════════════════════');
console.log('📊 迁移结果验证\n');
const templates = await prisma.prompt_templates.findMany({
where: { module: 'RVW' },
include: {
versions: {
orderBy: { version: 'desc' },
take: 1,
},
},
});
console.log(`✅ 共迁移 ${templates.length} 个 RVW Prompt:\n`);
for (const t of templates) {
const latestVersion = t.versions[0];
console.log(` 📋 ${t.code}`);
console.log(` 名称: ${t.name}`);
console.log(` 变量: ${t.variables ? JSON.stringify(t.variables) : '无'}`);
console.log(` 最新版本: v${latestVersion?.version} (${latestVersion?.status})`);
console.log('');
}
console.log('✅ RVW Prompt 迁移完成!');
}
main()
.catch((error) => {
console.error('❌ 迁移失败:', error);
process.exit(1);
})
.finally(() => prisma.$disconnect());