feat(ssa): Complete Phase 2A frontend integration - multi-step workflow end-to-end

Phase 2A: WorkflowPlannerService, WorkflowExecutorService, Python data quality, 6 bug fixes, DescriptiveResultView, multi-step R code/Word export, MVP UI reuse. V11 UI: Gemini-style, multi-task, single-page scroll, Word export. Architecture: Block-based rendering consensus (4 block types). New R tools: chi_square, correlation, descriptive, logistic_binary, mann_whitney, t_test_paired. Docs: dev summary, block-based plan, status updates, task list v2.0.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-20 23:09:27 +08:00
parent 23b422f758
commit 428a22adf2
62 changed files with 15416 additions and 299 deletions

View File

@@ -10,7 +10,7 @@ import { useSSAStore } from '../stores/ssaStore';
import { useAnalysis } from '../hooks/useAnalysis';
export const SSACodeModal: React.FC = () => {
const { codeModalVisible, setCodeModalVisible, executionResult, addToast } = useSSAStore();
const { codeModalVisible, setCodeModalVisible, executionResult, addToast, isWorkflowMode, workflowSteps } = useSSAStore();
const { downloadCode } = useAnalysis();
const [code, setCode] = useState<string>('');
const [isLoading, setIsLoading] = useState(false);
@@ -24,9 +24,21 @@ export const SSACodeModal: React.FC = () => {
const loadCode = async () => {
setIsLoading(true);
try {
const result = await downloadCode();
const text = await result.blob.text();
setCode(text);
if (isWorkflowMode && workflowSteps.length > 0) {
const allCode = workflowSteps
.filter(s => s.status === 'success' && s.result)
.map(s => {
const stepCode = (s.result as any)?.reproducible_code;
const header = `# ========================================\n# 步骤 ${s.step_number}: ${s.tool_name}\n# ========================================\n`;
return header + (stepCode || `# 该步骤暂无可用代码`);
})
.join('\n\n');
setCode(allCode || '# 暂无可用代码\n# 请先执行分析');
} else {
const result = await downloadCode();
const text = await result.blob.text();
setCode(text);
}
} catch (error) {
if (executionResult?.reproducibleCode) {
setCode(executionResult.reproducibleCode);
@@ -46,15 +58,27 @@ export const SSACodeModal: React.FC = () => {
const handleDownload = async () => {
try {
const result = await downloadCode();
const url = URL.createObjectURL(result.blob);
const a = document.createElement('a');
a.href = url;
a.download = result.filename;
a.click();
URL.revokeObjectURL(url);
addToast('R 脚本已下载', 'success');
handleClose();
if (isWorkflowMode && code) {
const blob = new Blob([code], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'workflow_analysis.R';
a.click();
URL.revokeObjectURL(url);
addToast('R 脚本已下载', 'success');
handleClose();
} else {
const result = await downloadCode();
const url = URL.createObjectURL(result.blob);
const a = document.createElement('a');
a.href = url;
a.download = result.filename;
a.click();
URL.revokeObjectURL(url);
addToast('R 脚本已下载', 'success');
handleClose();
}
} catch (error) {
addToast('下载失败', 'error');
}