feat(rvw): Complete RVW module development Phase 1-3

Summary:
- Migrate backend to modules/rvw with v2 API routes (/api/v2/rvw)
- Add new database fields: selectedAgents, editorialScore, methodologyStatus, picoExtract, isArchived
- Create frontend module in frontend-v2/src/modules/rvw
- Implement Dashboard with task list, filtering, batch operations
- Implement ReportDetail with dual tabs (editorial/methodology)
- Implement AgentModal for intelligent agent selection
- Register RVW module in moduleRegistry.ts
- Add navigation entry in TopNavigation
- Update documentation for RVW module status (v3.0)
- Update system status document (v2.9)

Features:
- User can select agents: editorial, methodology, or both
- Support batch task execution
- Task status filtering
- Replace console.log with logger service
- Maintain v1 API backward compatibility

Tested: Frontend and backend verified locally
Status: 85% complete (Phase 1-3 done)
This commit is contained in:
2026-01-07 22:39:08 +08:00
parent 06028c6952
commit 179afa2c6b
226 changed files with 5860 additions and 21 deletions

View File

@@ -0,0 +1,70 @@
/**
* RVW稿件审查模块 - 方法学评估服务
* @module rvw/services/methodologyService
*/
import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';
import { LLMFactory } from '../../../common/llm/adapters/LLMFactory.js';
import { ModelType } from '../../../common/llm/adapters/types.js';
import { logger } from '../../../common/logging/index.js';
import { MethodologyReview } from '../types/index.js';
import { parseJSONFromLLMResponse } from './utils.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Prompt文件路径
const PROMPT_PATH = path.join(__dirname, '../../../../prompts/review_methodology_system.txt');
/**
* 方法学评估
* @param text 稿件文本
* @param modelType 模型类型
* @returns 评估结果
*/
export async function reviewMethodology(
text: string,
modelType: ModelType = 'deepseek-v3'
): Promise<MethodologyReview> {
try {
// 1. 读取系统Prompt
const systemPrompt = await fs.readFile(PROMPT_PATH, 'utf-8');
// 2. 构建消息
const messages = [
{ role: 'system' as const, content: systemPrompt },
{ role: 'user' as const, content: `请对以下稿件进行方法学评估:\n\n${text}` },
];
// 3. 调用LLM
logger.info('[RVW:Methodology] 开始方法学评估', { modelType });
const llmAdapter = LLMFactory.getAdapter(modelType);
const response = await llmAdapter.chat(messages, {
temperature: 0.3,
maxTokens: 8000,
});
logger.info('[RVW:Methodology] 评估完成', {
modelType,
responseLength: response.content.length
});
// 4. 解析JSON响应
const result = parseJSONFromLLMResponse<MethodologyReview>(response.content);
// 5. 验证响应格式
if (!result || typeof result.overall_score !== 'number' || !Array.isArray(result.parts)) {
throw new Error('LLM返回的数据格式不正确');
}
return result;
} catch (error) {
logger.error('[RVW:Methodology] 方法学评估失败', {
error: error instanceof Error ? error.message : 'Unknown error',
stack: error instanceof Error ? error.stack : undefined,
});
throw new Error(`方法学评估失败: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}