feat(dc): Complete Tool B frontend development with UI optimization
- Implement Tool B 5-step workflow (upload, schema, processing, verify, result) - Add back navigation button to Portal - Optimize Step 2 field list styling to match prototype - Fix step 3 label: 'dual-blind' to 'dual-model' - Create API service layer with 7 endpoints - Integrate Tool B route into DC module - Add comprehensive TypeScript types Components (~1100 lines): - index.tsx: Main Tool B entry with state management - Step1Upload.tsx: File upload and health check - Step2Schema.tsx: Smart template configuration - Step3Processing.tsx: Dual-model extraction progress - Step4Verify.tsx: Conflict verification workbench - Step5Result.tsx: Result display - StepIndicator.tsx: Step progress component - api/toolB.ts: API service layer Status: Frontend complete, ready for API integration
This commit is contained in:
178
frontend-v2/src/modules/dc/api/toolB.ts
Normal file
178
frontend-v2/src/modules/dc/api/toolB.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Tool B API 服务层
|
||||
* 病历结构化机器人 API调用
|
||||
*/
|
||||
|
||||
const API_BASE = '/api/v1/dc/tool-b';
|
||||
|
||||
export interface HealthCheckRequest {
|
||||
fileKey: string;
|
||||
columnName: string;
|
||||
}
|
||||
|
||||
export interface HealthCheckResponse {
|
||||
status: 'good' | 'bad';
|
||||
emptyRate: number;
|
||||
avgLength: number;
|
||||
totalRows: number;
|
||||
estimatedTokens: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface Template {
|
||||
diseaseType: string;
|
||||
reportType: string;
|
||||
displayName: string;
|
||||
fields: Array<{
|
||||
name: string;
|
||||
desc: string;
|
||||
width?: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface CreateTaskRequest {
|
||||
projectName: string;
|
||||
fileKey: string;
|
||||
textColumn: string;
|
||||
diseaseType: string;
|
||||
reportType: string;
|
||||
targetFields: Array<{
|
||||
name: string;
|
||||
desc: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface CreateTaskResponse {
|
||||
taskId: string;
|
||||
}
|
||||
|
||||
export interface TaskProgress {
|
||||
taskId: string;
|
||||
status: 'pending' | 'processing' | 'completed' | 'failed';
|
||||
progress: number;
|
||||
totalRows: number;
|
||||
processedRows: number;
|
||||
conflictCount?: number;
|
||||
estimatedTime?: string;
|
||||
logs: string[];
|
||||
}
|
||||
|
||||
export interface ExtractionItem {
|
||||
id: string;
|
||||
rowIndex: number;
|
||||
originalText: string;
|
||||
status: 'clean' | 'conflict';
|
||||
extractedData: Record<string, {
|
||||
modelA: string;
|
||||
modelB: string;
|
||||
chosen: string | null;
|
||||
}>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 健康检查API
|
||||
*/
|
||||
export async function healthCheck(request: HealthCheckRequest): Promise<HealthCheckResponse> {
|
||||
const response = await fetch(`${API_BASE}/health-check`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Health check failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模板列表
|
||||
*/
|
||||
export async function getTemplates(): Promise<{ templates: Template[] }> {
|
||||
const response = await fetch(`${API_BASE}/templates`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Get templates failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建提取任务
|
||||
*/
|
||||
export async function createTask(request: CreateTaskRequest): Promise<CreateTaskResponse> {
|
||||
const response = await fetch(`${API_BASE}/tasks`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Create task failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询任务进度
|
||||
*/
|
||||
export async function getTaskProgress(taskId: string): Promise<TaskProgress> {
|
||||
const response = await fetch(`${API_BASE}/tasks/${taskId}/progress`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Get task progress failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取验证网格数据
|
||||
*/
|
||||
export async function getTaskItems(taskId: string): Promise<{ items: ExtractionItem[] }> {
|
||||
const response = await fetch(`${API_BASE}/tasks/${taskId}/items`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Get task items failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 裁决冲突
|
||||
*/
|
||||
export async function resolveConflict(
|
||||
itemId: string,
|
||||
fieldName: string,
|
||||
value: string
|
||||
): Promise<{ success: boolean }> {
|
||||
const response = await fetch(`${API_BASE}/items/${itemId}/resolve`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ fieldName, chosenValue: value }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Resolve conflict failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出结果
|
||||
*/
|
||||
export async function exportResults(taskId: string): Promise<Blob> {
|
||||
const response = await fetch(`${API_BASE}/tasks/${taskId}/export`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Export results failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.blob();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user