feat(rvw): Complete Phase 4-5 - Bug fixes and Word export

Summary:
- Fix methodology score display issue in task list (show score instead of 'warn')
- Add methodology_score field to database schema
- Fix report display when only methodology agent is selected
- Implement Word document export using docx library
- Update documentation to v3.0/v3.1

Backend changes:
- Add methodologyScore to Prisma schema and TaskSummary type
- Update reviewWorker to save methodologyScore
- Update getTaskList to return methodologyScore

Frontend changes:
- Install docx and file-saver libraries
- Implement handleExportReport with Word generation
- Fix activeTab auto-selection based on available data
- Add proper imports for docx components

Documentation:
- Update RVW module status to 90% (Phase 1-5 complete)
- Update system status document to v3.0

Tested: All review workflows verified, Word export functional
This commit is contained in:
2026-01-10 22:52:15 +08:00
parent 179afa2c6b
commit 440f75255e
237 changed files with 3942 additions and 657 deletions

View File

@@ -39,3 +39,5 @@ Status: Day 1 complete (11/11 tasks), ready for Day 2

View File

@@ -266,6 +266,8 @@

View File

@@ -215,3 +215,5 @@ https://iit.xunzhengyixue.com/api/v1/iit/health

View File

@@ -144,3 +144,5 @@ https://iit.xunzhengyixue.com/api/v1/iit/health

View File

@@ -45,3 +45,5 @@

View File

@@ -305,3 +305,5 @@ npx tsx src/modules/iit-manager/test-patient-wechat-url-verify.ts

View File

@@ -167,3 +167,5 @@ npm run dev

View File

@@ -61,6 +61,8 @@ WHERE table_schema = 'dc_schema'

View File

@@ -99,6 +99,8 @@ ORDER BY ordinal_position;

View File

@@ -112,6 +112,8 @@ runMigration()

View File

@@ -46,6 +46,8 @@ COMMENT ON COLUMN "dc_schema"."dc_tool_c_sessions"."column_mapping" IS '列名

View File

@@ -73,6 +73,8 @@ COMMENT ON COLUMN dc_schema.dc_tool_c_sessions.expires_at IS '过期时间(创

View File

@@ -314,6 +314,7 @@ model ReviewTask {
// 🆕 结果摘要Phase 2新增用于列表展示
editorialScore Float? @map("editorial_score")
methodologyScore Float? @map("methodology_score")
methodologyStatus String? @map("methodology_status") // pass/warn/fail
// 🆕 预留字段(暂不使用)

View File

@@ -113,6 +113,8 @@ Write-Host ""

View File

@@ -223,6 +223,8 @@ function extractCodeBlocks(obj, blocks = []) {

View File

@@ -242,6 +242,8 @@ checkDCTables();

View File

@@ -194,6 +194,8 @@ createAiHistoryTable()

View File

@@ -181,6 +181,8 @@ createToolCTable()

View File

@@ -178,6 +178,8 @@ createToolCTable()

View File

@@ -328,3 +328,5 @@ runTests().catch(error => {

View File

@@ -293,3 +293,5 @@ verifySchemas()

View File

@@ -310,6 +310,8 @@ export function getBatchItems<T>(

View File

@@ -20,6 +20,7 @@ import { registerTestRoutes } from './test-platform-api.js';
import { registerScreeningWorkers } from './modules/asl/services/screeningWorker.js';
import { registerExtractionWorkers } from './modules/dc/tool-b/workers/extractionWorker.js';
import { registerParseExcelWorker } from './modules/dc/tool-c/workers/parseExcelWorker.js';
import { registerReviewWorker } from './modules/rvw/workers/reviewWorker.js';
import { jobQueue } from './common/jobs/index.js';
@@ -183,6 +184,10 @@ const start = async () => {
registerParseExcelWorker();
logger.info('✅ DC Tool C parse excel worker registered');
// 注册RVW审稿Worker
registerReviewWorker();
logger.info('✅ RVW review worker registered');
// 注册IIT Manager Workers
await initIitManager();
logger.info('✅ IIT Manager workers registered');
@@ -201,6 +206,7 @@ const start = async () => {
console.log(' - asl_screening_batch (文献筛选批次处理)');
console.log(' - dc_extraction_batch (数据提取批次处理)');
console.log(' - dc_toolc_parse_excel (Tool C Excel解析)');
console.log(' - rvw_review_task (稿件审查任务)');
console.log(' - iit_quality_check (IIT质控+企微推送)');
console.log(' - iit_redcap_poll (IIT REDCap轮询)');
console.log('='.repeat(60) + '\n');

View File

@@ -346,6 +346,8 @@ runTests().catch((error) => {

View File

@@ -325,6 +325,8 @@ Content-Type: application/json

View File

@@ -261,6 +261,8 @@ export const conflictDetectionService = new ConflictDetectionService();

View File

@@ -211,6 +211,8 @@ curl -X POST http://localhost:3000/api/v1/dc/tool-c/test/execute \

View File

@@ -265,6 +265,8 @@ export const streamAIController = new StreamAIController();

View File

@@ -177,3 +177,5 @@ logger.info('[SessionMemory] 会话记忆管理器已启动', {

View File

@@ -111,3 +111,5 @@ checkTableStructure();

View File

@@ -98,3 +98,5 @@ checkProjectConfig().catch(console.error);

View File

@@ -80,3 +80,5 @@ main();

View File

@@ -537,3 +537,5 @@ URL: https://iit.xunzhengyixue.com/api/v1/iit/patient-wechat/callback

View File

@@ -172,3 +172,5 @@ console.log('');

View File

@@ -489,3 +489,5 @@ export const patientWechatService = new PatientWechatService();

View File

@@ -134,3 +134,5 @@ testDifyIntegration().catch(error => {

View File

@@ -163,3 +163,5 @@ testIitDatabase()

View File

@@ -149,3 +149,5 @@ if (hasError) {

View File

@@ -175,3 +175,5 @@ async function testUrlVerification() {

View File

@@ -256,3 +256,5 @@ main().catch((error) => {

View File

@@ -140,3 +140,5 @@ Write-Host ""

View File

@@ -233,3 +233,5 @@ export interface CachedProtocolRules {

View File

@@ -46,3 +46,5 @@ export default async function healthRoutes(fastify: FastifyInstance) {

View File

@@ -124,3 +124,5 @@ Content-Type: application/json
GET {{baseUrl}}/api/v1/review/tasks/{{taskId}}/report
Content-Type: application/json

View File

@@ -109,3 +109,5 @@ Write-Host " - 查看报告: GET $BaseUrl/api/v2/rvw/tasks/{taskId}/report" -Fo
Write-Host " - 批量运行: POST $BaseUrl/api/v2/rvw/tasks/batch/run" -ForegroundColor Gray
Write-Host " - 删除任务: DELETE $BaseUrl/api/v2/rvw/tasks/{taskId}" -ForegroundColor Gray

View File

@@ -136,6 +136,8 @@ export async function createTask(
/**
* 运行审查(选择智能体)
* POST /api/v2/rvw/tasks/:taskId/run
*
* ✅ Platform-Only架构返回 jobId 供前端轮询
*/
export async function runReview(
request: FastifyRequest<{
@@ -151,11 +153,16 @@ export async function runReview(
logger.info('[RVW:Controller] 运行审查', { taskId, agents });
await reviewService.runReview({ taskId, agents, userId });
// ✅ 返回 jobIdPlatform-Only架构
const { jobId } = await reviewService.runReview({ taskId, agents, userId });
return reply.send({
success: true,
message: '审查任务已启动',
data: {
taskId,
jobId, // ✅ 供前端轮询状态
},
});
} catch (error) {
logger.error('[RVW:Controller] 运行审查失败', {

View File

@@ -23,3 +23,5 @@ export * from './types/index.js';
// 导出工具函数
export * from './services/utils.js';

View File

@@ -44,3 +44,5 @@ export default async function rvwRoutes(fastify: FastifyInstance) {
fastify.post('/tasks/batch/run', reviewController.batchRunReview);
}

View File

@@ -68,3 +68,5 @@ export async function reviewEditorialStandards(
}
}

View File

@@ -68,3 +68,5 @@ export async function reviewMethodology(
}
}

View File

@@ -15,6 +15,7 @@ import { prisma } from '../../../config/database.js';
import { extractionClient } from '../../../common/document/ExtractionClient.js';
import { ModelType } from '../../../common/llm/adapters/types.js';
import { logger } from '../../../common/logging/index.js';
import { jobQueue } from '../../../common/jobs/index.js';
import { Prisma } from '@prisma/client';
import {
AgentType,
@@ -124,9 +125,15 @@ async function extractDocumentAsync(taskId: string, file: Buffer, filename: stri
/**
* 运行审查(核心功能)
* 支持选择1个或2个智能体
*
* ✅ Platform-Only架构
* - 使用 pg-boss 队列处理审查任务
* - API 立即返回 jobId
* - 后台 Worker 执行实际审查
*
* @returns jobId 供前端轮询状态
*/
export async function runReview(params: RunReviewParams): Promise<void> {
export async function runReview(params: RunReviewParams): Promise<{ jobId: string }> {
const { taskId, agents, userId } = params;
// 验证智能体选择
@@ -149,91 +156,38 @@ export async function runReview(params: RunReviewParams): Promise<void> {
throw new Error('文档尚未提取完成,请稍后再试');
}
const startTime = Date.now();
// 更新任务状态为reviewing
await prisma.reviewTask.update({
where: { id: taskId },
data: {
status: 'reviewing',
selectedAgents: agents,
startedAt: new Date(),
// 清除之前的结果(如果重新运行)
editorialReview: Prisma.JsonNull,
methodologyReview: Prisma.JsonNull,
overallScore: null,
errorMessage: null,
},
});
try {
// 更新任务状态
await prisma.reviewTask.update({
where: { id: taskId },
data: {
status: 'reviewing',
startedAt: new Date(),
// 清除之前的结果(如果重新运行)
editorialReview: Prisma.JsonNull,
methodologyReview: Prisma.JsonNull,
overallScore: null,
errorMessage: null,
},
});
// ✅ 推送任务到 pg-boss 队列Platform-Only架构
const job = await jobQueue.push('rvw_review_task', {
taskId,
userId,
agents,
extractedText: task.extractedText,
modelType: (task.modelUsed || 'deepseek-v3') as ModelType,
});
logger.info('[RVW] 开始审查', { taskId, agents });
logger.info('[RVW] 审查任务已推送到队列', {
taskId,
jobId: job.id,
agents,
});
// 获取模型类型
const modelType = (task.modelUsed || 'deepseek-v3') as ModelType;
// 运行选中的智能体
let editorialResult: EditorialReview | null = null;
let methodologyResult: MethodologyReview | null = null;
if (agents.includes('editorial')) {
logger.info('[RVW] 运行稿约规范性智能体', { taskId });
editorialResult = await reviewEditorialStandards(task.extractedText, modelType);
}
if (agents.includes('methodology')) {
logger.info('[RVW] 运行方法学智能体', { taskId });
methodologyResult = await reviewMethodology(task.extractedText, modelType);
}
// 计算综合分数
const editorialScore = editorialResult?.overall_score ?? null;
const methodologyScore = methodologyResult?.overall_score ?? null;
const overallScore = calculateOverallScore(editorialScore, methodologyScore, agents);
// 计算耗时
const endTime = Date.now();
const durationSeconds = Math.floor((endTime - startTime) / 1000);
// 更新任务结果(使用新字段)
await prisma.reviewTask.update({
where: { id: taskId },
data: {
status: 'completed',
editorialReview: editorialResult as unknown as Prisma.InputJsonValue ?? Prisma.JsonNull,
methodologyReview: methodologyResult as unknown as Prisma.InputJsonValue ?? Prisma.JsonNull,
overallScore,
// 🆕 使用新字段存储摘要信息
editorialScore: editorialScore,
methodologyStatus: getMethodologyStatus(methodologyResult),
completedAt: new Date(),
durationSeconds,
},
});
logger.info('[RVW] 审查完成', {
taskId,
agents,
editorialScore,
methodologyScore,
overallScore,
durationSeconds,
});
} catch (error) {
logger.error('[RVW] 审查失败', {
taskId,
error: error instanceof Error ? error.message : 'Unknown error'
});
await prisma.reviewTask.update({
where: { id: taskId },
data: {
status: 'failed',
errorMessage: error instanceof Error ? error.message : 'Review failed',
},
});
throw error;
}
// ✅ 立即返回 jobId不阻塞请求
return { jobId: job.id };
}
/**
@@ -324,6 +278,7 @@ export async function getTaskList(params: TaskListParams): Promise<TaskListRespo
// 🆕 使用新字段
selectedAgents: true,
editorialScore: true,
methodologyScore: true,
methodologyStatus: true,
overallScore: true,
modelUsed: true,
@@ -344,6 +299,7 @@ export async function getTaskList(params: TaskListParams): Promise<TaskListRespo
status: task.status as TaskStatus,
selectedAgents: (task.selectedAgents || ['editorial', 'methodology']) as AgentType[],
editorialScore: task.editorialScore ?? undefined,
methodologyScore: task.methodologyScore ?? undefined,
methodologyStatus: task.methodologyStatus as any,
overallScore: task.overallScore ?? undefined,
modelUsed: task.modelUsed ?? undefined,

View File

@@ -114,3 +114,5 @@ export function validateAgentSelection(agents: string[]): void {
}
}

View File

@@ -107,6 +107,7 @@ export interface TaskSummary {
status: TaskStatus;
selectedAgents: AgentType[];
editorialScore?: number;
methodologyScore?: number;
methodologyStatus?: MethodologyStatus;
overallScore?: number;
modelUsed?: string;
@@ -155,3 +156,5 @@ export interface LLMMessage {
content: string;
}

View File

@@ -0,0 +1,190 @@
/**
* RVW稿件审查 WorkerPlatform-Only架构
*
* ✅ Platform-Only架构
* - 使用 pg-boss 队列处理审查任务
* - 任务状态存储在 job.state (pg-boss管理)
* - 审查结果更新到 ReviewTask表业务信息
*
* 任务流程:
* 1. 获取任务信息和提取的文本
* 2. 根据选择的智能体执行审查
* 3. 更新任务状态和结果
*/
import { prisma } from '../../../config/database.js';
import { logger } from '../../../common/logging/index.js';
import { jobQueue } from '../../../common/jobs/index.js';
import type { Job } from '../../../common/jobs/types.js';
import { Prisma } from '@prisma/client';
import { ModelType } from '../../../common/llm/adapters/types.js';
import { reviewEditorialStandards } from '../services/editorialService.js';
import { reviewMethodology } from '../services/methodologyService.js';
import { calculateOverallScore, getMethodologyStatus } from '../services/utils.js';
import type { AgentType, EditorialReview, MethodologyReview } from '../types/index.js';
/**
* 审查任务数据结构
*/
interface ReviewJob {
taskId: string;
userId: string;
agents: AgentType[];
extractedText: string;
modelType: ModelType;
}
/**
* 注册审查 Worker 到队列
*
* 此函数应在应用启动时调用index.ts
*/
export function registerReviewWorker() {
logger.info('[reviewWorker] Registering reviewWorker');
// 注册审查Worker队列名使用下划线不用冒号
jobQueue.process<ReviewJob>('rvw_review_task', async (job: Job<ReviewJob>) => {
const { taskId, userId, agents, extractedText, modelType } = job.data;
const startTime = Date.now();
logger.info('[reviewWorker] Processing review job', {
jobId: job.id,
taskId,
userId,
agents,
textLength: extractedText.length,
});
console.log(`\n📝 处理审查任务`);
console.log(` Job ID: ${job.id}`);
console.log(` Task ID: ${taskId}`);
console.log(` 智能体: ${agents.join(', ')}`);
console.log(` 文本长度: ${extractedText.length} 字符`);
try {
// ========================================
// 1. 运行选中的智能体
// ========================================
let editorialResult: EditorialReview | null = null;
let methodologyResult: MethodologyReview | null = null;
if (agents.includes('editorial')) {
// 更新进度状态
await prisma.reviewTask.update({
where: { id: taskId },
data: { status: 'reviewing_editorial' },
});
logger.info('[reviewWorker] Running editorial review', { taskId });
console.log(' 🔍 运行稿约规范性智能体...');
editorialResult = await reviewEditorialStandards(extractedText, modelType);
logger.info('[reviewWorker] Editorial review completed', {
taskId,
score: editorialResult?.overall_score,
});
console.log(` ✅ 稿约规范性完成,得分: ${editorialResult?.overall_score}`);
}
if (agents.includes('methodology')) {
// 更新进度状态
await prisma.reviewTask.update({
where: { id: taskId },
data: { status: 'reviewing_methodology' },
});
logger.info('[reviewWorker] Running methodology review', { taskId });
console.log(' 🔬 运行方法学智能体...');
methodologyResult = await reviewMethodology(extractedText, modelType);
logger.info('[reviewWorker] Methodology review completed', {
taskId,
score: methodologyResult?.overall_score,
});
console.log(` ✅ 方法学评估完成,得分: ${methodologyResult?.overall_score}`);
}
// ========================================
// 2. 计算综合分数
// ========================================
const editorialScore = editorialResult?.overall_score ?? null;
const methodologyScore = methodologyResult?.overall_score ?? null;
const overallScore = calculateOverallScore(editorialScore, methodologyScore, agents);
// 计算耗时
const endTime = Date.now();
const durationSeconds = Math.floor((endTime - startTime) / 1000);
// ========================================
// 3. 更新任务结果
// ========================================
logger.info('[reviewWorker] Updating task result', { taskId });
await prisma.reviewTask.update({
where: { id: taskId },
data: {
status: 'completed',
editorialReview: editorialResult as unknown as Prisma.InputJsonValue ?? Prisma.JsonNull,
methodologyReview: methodologyResult as unknown as Prisma.InputJsonValue ?? Prisma.JsonNull,
overallScore,
editorialScore: editorialScore,
methodologyScore: methodologyScore,
methodologyStatus: getMethodologyStatus(methodologyResult),
completedAt: new Date(),
durationSeconds,
},
});
logger.info('[reviewWorker] ✅ Review completed', {
jobId: job.id,
taskId,
agents,
editorialScore,
methodologyScore,
overallScore,
durationSeconds,
});
console.log('\n✅ 审查完成:');
console.log(` Task ID: ${taskId}`);
console.log(` 综合得分: ${overallScore}`);
console.log(` 耗时: ${durationSeconds}`);
return {
taskId,
overallScore,
editorialScore,
methodologyScore,
durationSeconds,
success: true,
};
} catch (error: any) {
logger.error('[reviewWorker] ❌ Review failed', {
jobId: job.id,
taskId,
error: error.message,
stack: error.stack,
});
console.error(`\n❌ 审查失败: ${error.message}`);
// 更新任务状态为失败
await prisma.reviewTask.update({
where: { id: taskId },
data: {
status: 'failed',
errorMessage: error.message || 'Review failed',
},
});
// 抛出错误,让 pg-boss 处理重试
throw error;
}
});
logger.info('[reviewWorker] ✅ Worker registered: rvw_review_task');
}

View File

@@ -411,6 +411,8 @@ SET session_replication_role = 'origin';

View File

@@ -113,6 +113,8 @@ WHERE key = 'verify_test';

View File

@@ -256,6 +256,8 @@ verifyDatabase()

View File

@@ -46,6 +46,8 @@ export {}

View File

@@ -69,6 +69,8 @@ Write-Host "✅ 完成!" -ForegroundColor Green

View File

@@ -160,3 +160,5 @@ DELETE {{baseUrl}}/api/v2/pkb/knowledge/knowledge-bases/{{testKbId}}

View File

@@ -356,6 +356,8 @@ runAdvancedTests().catch(error => {

View File

@@ -422,6 +422,8 @@ runAllTests()

View File

@@ -380,6 +380,8 @@ runAllTests()

View File

@@ -164,6 +164,8 @@ Set-Location ..

View File

@@ -1,10 +1,10 @@
# AIclinicalresearch 系统当前状态与开发指南
> **文档版本:** v2.9
> **文档版本:** v3.0
> **创建日期:** 2025-11-28
> **维护者:** 开发团队
> **最后更新:** 2026-01-07
> **重大进展:** 🎉 **RVW稿件审查模块开发完成85%** - 后端迁移+数据库扩展+前端重构全部完成
> **最后更新:** 2026-01-10
> **重大进展:** 🎉 **RVW稿件审查模块开发完成90%** - 后端迁移+数据库扩展+前端重构+Word导出全部完成
> **部署状态:** ✅ 生产环境运行中 | 公网地址http://8.140.53.236/
> **文档目的:** 快速了解系统当前状态为新AI助手提供上下文
@@ -45,7 +45,7 @@
| **IIT** | IIT Manager Agent | AI驱动IIT研究助手 - 智能质控+REDCap集成 | ⭐⭐⭐⭐⭐ | 🎉 **Phase 1.5完成60%- AI对话+REDCap数据集成** | **P0** |
| **SSA** | 智能统计分析 | 队列/预测模型/RCT分析 | ⭐⭐⭐⭐⭐ | 📋 规划中 | P2 |
| **ST** | 统计分析工具 | 100+轻量化统计工具 | ⭐⭐⭐⭐ | 📋 规划中 | P2 |
| **RVW** | 稿件审查系统 | 方法学评估、审稿流程 | ⭐⭐⭐⭐ | ✅ **开发完成(85%** | P3 |
| **RVW** | 稿件审查系统 | 方法学评估、审稿流程、Word导出 | ⭐⭐⭐⭐ | ✅ **开发完成(90%** | P3 |
---
@@ -815,7 +815,7 @@ npm run dev # http://localhost:3000
- **总计**:约 85,000 行
### 模块完成度
-**已完成**AIA100%、平台基础层100%、RVW85%Phase 1-3完成)
-**已完成**AIA100%、平台基础层100%、RVW90%Phase 1-5完成支持Word导出
- 🚧 **开发中**PKB90%核心功能完成、ASL80%、DCTool C 98%Tool B后端100%Tool B前端0%、IIT60%Phase 1.5完成)
- 📋 **未开始**SSA、ST
@@ -953,8 +953,8 @@ if (items.length >= 50) {
---
**文档版本**v2.9
**最后更新**2026-01-07
**文档版本**v3.0
**最后更新**2026-01-10
**下次更新**RVW生产环境部署 或 ASL智能文献筛选模块启动
---
@@ -1020,7 +1020,7 @@ if (items.length >= 50) {
---
**RVW稿件审查模块开发完成2026-01-07**
**RVW稿件审查模块开发完成2026-01-07 ~ 2026-01-10**
### Phase 1后端模块迁移与扩展
- ✅ 创建 `backend/src/modules/rvw/` 模块结构
@@ -1029,24 +1029,36 @@ if (items.length >= 50) {
- ✅ 实现批量运行APIbatchRunReviewTasks
- ✅ 替换 console.log 为 logger 服务
- ✅ 注册 v2 API路由/api/v2/rvw
- ✅ 实现 pg-boss 异步任务处理reviewWorker
### Phase 2数据库字段扩展
- ✅ 添加 selectedAgents、editorialScore、methodologyStatus 字段
- ✅ 添加 selectedAgents、editorialScore、methodologyScore、methodologyStatus 字段
- ✅ 添加 picoExtract、isArchived、archivedAt 字段
- ✅ 使用 prisma db push 同步到数据库
### Phase 3前端重构frontend-v2
- ✅ 创建 `frontend-v2/src/modules/rvw/index.tsx`~503行
- ✅ 实现 Dashboard 组件(任务列表、筛选、批量操作)
- ✅ 实现 ReportDetail 组件(双标签页切换
- ✅ 创建 `frontend-v2/src/modules/rvw/` 完整模块目录结构
- ✅ 实现 Dashboard 页面(任务列表、筛选、批量操作)
- ✅ 实现 TaskDetail 组件(审稿进度条、实时状态轮询
- ✅ 实现 EditorialReport/MethodologyReport 组件
- ✅ 实现 AgentModal 组件(智能体选择弹窗)
- ✅ 注册到 moduleRegistry.ts
- ✅ 添加顶部导航"预审稿"入口
### Phase 4集成测试与Bug修复2026-01-10
- ✅ 修复方法学分数不显示问题
- ✅ 修复只选方法学时详情页不显示报告问题
- ✅ 完整测试单智能体和双智能体审稿流程
### Phase 5报告导出2026-01-10
- ✅ 安装 docx 和 file-saver 库
- ✅ 实现 Word 文档导出功能
- ✅ 支持结构化报告(标题、基本信息、稿约规范性、方法学评估)
**技术亮点**
- 🔥 **新旧API兼容**v1 + v2 API同时运行
- 🔥 **智能体可选**:用户可选择运行稿约规范性/方法学/两者
- 🔥 **批量操作**:支持多选任务批量运行
- 🔥 **异步任务处理**:使用 pg-boss 队列处理长时间审稿任务
- 🔥 **Word导出**:使用 docx 库生成专业格式的审稿报告
- 🔥 **云原生改造**:使用 logger 服务,遵循开发规范
**模块进度**85%完成Phase 1-3
**模块进度**90%完成Phase 1-5

View File

@@ -606,6 +606,8 @@ async saveProcessedData(recordId, newData) {

View File

@@ -793,6 +793,8 @@ export const AsyncProgressBar: React.FC<AsyncProgressBarProps> = ({

View File

@@ -1286,6 +1286,8 @@ interface FulltextScreeningResult {

View File

@@ -400,6 +400,8 @@ GET /api/v1/asl/fulltext-screening/tasks/:taskId/export

View File

@@ -502,6 +502,8 @@ Failed to open file '\\tmp\\extraction_service\\temp_10000_test.pdf'

View File

@@ -568,6 +568,8 @@ df['creatinine'] = pd.to_numeric(df['creatinine'], errors='coerce')

View File

@@ -983,6 +983,8 @@ export const aiController = new AIController();

View File

@@ -1317,6 +1317,8 @@ npm install react-markdown

View File

@@ -225,6 +225,8 @@ FMA___基线 | FMA___1个月 | FMA___2个月

View File

@@ -383,6 +383,8 @@ formula = "FMA总分0-100 / 100"

View File

@@ -217,6 +217,8 @@ async handleFillnaMice(request, reply) {

View File

@@ -189,6 +189,8 @@ method: 'mean' | 'median' | 'mode' | 'constant' | 'ffill' | 'bfill'

View File

@@ -640,6 +640,8 @@ import { logger } from '../../../../common/logging/index.js';

View File

@@ -443,6 +443,8 @@ import { ChatContainer } from '@/shared/components/Chat';

View File

@@ -353,6 +353,8 @@ const initialMessages = defaultMessages.length > 0 ? defaultMessages : [{

View File

@@ -641,6 +641,8 @@ http://localhost:5173/data-cleaning/tool-c

View File

@@ -429,6 +429,8 @@ Docs: docs/03-业务模块/DC-数据清洗整理/06-开发记录/DC模块重建

View File

@@ -302,6 +302,8 @@ ConflictDetectionService // 冲突检测(字段级对比)

View File

@@ -466,6 +466,8 @@ Tool B后端代码**100%复用**了平台通用能力层,无任何重复开发

Some files were not shown because too many files have changed in this diff Show More