# MiroFish 前端功能演示 ## 首页功能详解 ### 1. 页面整体布局 ``` ┌─────────────────────────────────────────────────┐ │ │ │ [MiroFish Logo] │ │ │ │ 上传任意报告,模拟世界即刻开始 │ │ │ ├─────────────────────────────────────────────────┤ │ │ │ 模拟需求 │ │ ┌───────────────────────────────────────────┐ │ │ │ 请描述您的模拟需求... │ │ │ │ │ │ │ │ │ │ │ └───────────────────────────────────────────┘ │ │ │ │ 项目名称 (可选) │ │ ┌───────────────────────────────────────────┐ │ │ │ 为您的项目命名 │ │ │ └───────────────────────────────────────────┘ │ │ │ │ 上传文档 │ │ ┌───────────────────────────────────────────┐ │ │ │ 📤 │ │ │ │ 点击或拖拽文件到此处 │ │ │ │ 支持 PDF、Markdown、TXT 格式 │ │ │ └───────────────────────────────────────────┘ │ │ │ │ 额外说明 (可选) │ │ ┌───────────────────────────────────────────┐ │ │ │ 如有其他需要补充的信息... │ │ │ └───────────────────────────────────────────┘ │ │ │ │ ┌───────────────────────────────────────────┐ │ │ │ 开 始 模 拟 │ │ │ └───────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────┘ ``` ### 2. 交互功能说明 #### 2.1 文件上传 **支持方式**: 1. **点击上传**: 点击上传区域,弹出文件选择对话框 2. **拖拽上传**: 直接拖拽文件到上传区域 **支持格式**: - PDF文档 (.pdf) - Markdown文档 (.md) - 纯文本文档 (.txt) **上传特性**: - ✅ 支持多文件上传 - ✅ 显示文件名和大小 - ✅ 可以删除已选择的文件 - ✅ 自动过滤不支持的格式 - ✅ 拖拽时高亮显示上传区域 **示例**: ``` 上传后显示: ┌─────────────────────────────────────────┐ │ 📄 report.pdf 2.5 MB [×] │ │ 📄 analysis.md 1.2 MB [×] │ └─────────────────────────────────────────┘ ``` #### 2.2 表单验证 **必填项检查**: - ❌ 未填写模拟需求 → 按钮禁用 - ❌ 未上传文件 → 按钮禁用 - ✅ 两者都完成 → 按钮可点击 **可选项**: - 项目名称(留空则自动生成) - 额外说明(留空则不传递) **状态提示**: - 按钮禁用时:灰色不可点击 - 按钮可用时:黑色背景,hover变白色背景 #### 2.3 提交流程 **步骤1: 用户点击"开始模拟"** ``` 按钮状态变为: ┌─────────────────────────────┐ │ ⌛ 处理中... │ └─────────────────────────────┘ ``` **步骤2: 构建FormData** ```javascript FormData包含: - files: [file1, file2, ...] - simulation_requirement: "用户输入的需求" - project_name: "项目名称" (可选) - additional_context: "额外说明" (可选) ``` **步骤3: 调用API** ``` POST /api/graph/ontology/generate Content-Type: multipart/form-data 自动重试机制: 第1次失败 → 等待1秒 → 重试 第2次失败 → 等待2秒 → 重试 第3次失败 → 等待4秒 → 重试 第4次失败 → 显示错误 ``` **步骤4: 成功响应** ```json { "success": true, "data": { "project_id": "proj_abc123", "project_name": "项目名称", "ontology": { ... }, ... } } ``` **步骤5: 页面跳转** ``` 跳转到: /process/proj_abc123 ``` #### 2.4 错误处理 **网络错误**: ``` ┌───────────────────────────────────────┐ │ ⚠ 提交失败,请检查网络连接或稍后重试 │ └───────────────────────────────────────┘ ``` **API错误**: ``` ┌───────────────────────────────────────┐ │ ⚠ 生成本体失败,请重试 │ └───────────────────────────────────────┘ ``` **文件格式错误**: ``` ┌───────────────────────────────────────┐ │ ⚠ 部分文件格式不支持,已自动过滤 │ └───────────────────────────────────────┘ ``` ### 3. 设计细节 #### 3.1 颜色方案 ```css /* 主色调 */ 黑色: #000000 (文字、边框、按钮) 白色: #FFFFFF (背景、按钮hover) 灰色: #666666 (次要文字) 浅灰: #f5f5f5 (禁用背景) /* 错误色 */ 红色: #ff0000 (错误提示边框和文字) 浅红: #fff5f5 (错误提示背景) ``` #### 3.2 边框样式 ```css /* 输入框 */ border: 1px solid #000000 /* 输入框聚焦 */ border: 2px solid #000000 /* 上传区域 */ border: 2px dashed #000000 /* 上传区域hover */ border: 2px dashed #333333 background: #fafafa /* 上传区域拖拽中 */ border: 2px solid #000000 background: #f0f0f0 ``` #### 3.3 字体样式 ```css /* Logo标语 */ font-size: 1.5rem (24px) font-weight: 300 letter-spacing: 0.05em /* 标签 */ font-size: 0.95rem (15.2px) font-weight: 500 letter-spacing: 0.02em /* 输入框 */ font-size: 0.95rem (15.2px) /* 按钮 */ font-size: 1.1rem (17.6px) font-weight: 500 letter-spacing: 0.1em ``` #### 3.4 间距设计 ```css /* 区块间距 */ margin-bottom: 1.5rem (24px) /* 内边距 */ 表单区域: padding: 2.5rem (40px) 输入框: padding: 0.75rem (12px) 按钮: padding: 1rem (16px) ``` ### 4. 响应式适配 #### 桌面端 (>= 768px) ``` 容器最大宽度: 800px 表单内边距: 2.5rem Logo最大宽度: 400px ``` #### 移动端 (< 768px) ``` 容器宽度: 100% 表单内边距: 1.5rem Logo最大宽度: 300px 标语字号: 1.2rem ``` ### 5. 动画效果 #### 加载动画 ```css @keyframes spin { to { transform: rotate(360deg); } } .loading-spinner { width: 16px; height: 16px; border: 2px solid #ffffff; border-top-color: transparent; border-radius: 50%; animation: spin 0.8s linear infinite; } ``` #### 按钮hover ```css transition: all 0.3s; /* Normal */ background: #000000; color: #ffffff; /* Hover */ background: #ffffff; color: #000000; ``` #### 输入框焦点 ```css transition: all 0.2s; /* Normal */ border: 1px solid #000000; /* Focus */ border: 2px solid #000000; ``` ## 第二页功能详解 ### 1. 页面布局 ``` ┌───────────────────┬─────────────────────────┐ │ │ │ │ 实时图谱 │ Step 1 - 现实种子构建 │ │ │ │ │ ┌─────────────┐ │ ① 文档分析 ✓ │ │ │ │ │ 正在分析上传的文档... │ │ │ 图谱 │ │ │ │ │ 可视化 │ │ ② 本体生成 ⌛ │ │ │ │ │ 使用LLM生成本体... │ │ │ │ │ │ │ └─────────────┘ │ ③ 图谱构建 │ │ │ 待处理... │ │ 节点数: 50 │ │ │ 关系数: 120 │ ④ 完成 │ │ │ 待处理... │ │ │ │ │ │ ─────────────────── │ │ │ 项目信息 │ │ │ 项目名称: ... │ │ │ 项目ID: proj_xxx │ │ │ 状态: graph_building │ │ │ │ └───────────────────┴─────────────────────────┘ ``` ### 2. 自动化流程 **页面加载**: 1. 从URL获取projectId 2. 调用 `GET /api/graph/project/{projectId}` 3. 根据项目状态更新UI **状态机**: ``` created → ontology_generated → graph_building → graph_completed ↓ ↓ ↓ ↓ 步骤1 步骤2 步骤3 步骤4 ``` **自动触发图谱构建**: ```javascript if (status === 'ontology_generated' && !graph_id) { // 自动调用 POST /api/graph/build await buildGraph({ project_id }) } ``` **轮询任务状态**: ```javascript setInterval(() => { // 每2秒调用 GET /api/graph/task/{taskId} const task = await getTaskStatus(taskId) // 更新进度显示 }, 2000) ``` **加载图谱数据**: ```javascript if (status === 'graph_completed' && graph_id) { // 调用 GET /api/graph/data/{graphId} const graphData = await getGraphData(graph_id) } ``` ### 3. 步骤指示器 **未开始状态**: ``` ○ 步骤标题 描述文字 opacity: 0.4 ``` **进行中状态**: ``` ● 步骤标题 描述文字 进度信息 (45%) opacity: 1.0 background: #000000 (number) color: #ffffff (number) ``` **已完成状态**: ``` ● 步骤标题 描述文字 已完成 ✓ opacity: 1.0 background: #000000 (number) ``` ## 使用示例 ### 完整流程演示 **场景**: 模拟武汉大学撤销处分事件的舆情走向 **步骤1**: 打开首页 ``` 访问: http://localhost:3000 ``` **步骤2**: 填写表单 ``` 模拟需求: "模拟武汉大学撤销处分通告发布后的舆情走向" 项目名称: "武汉大学舆情分析" 上传文档: report.pdf (关于事件的背景报告) ``` **步骤3**: 提交 ``` 点击"开始模拟"按钮 等待API响应(约5-30秒) ``` **步骤4**: 查看处理 ``` 自动跳转到: /process/proj_abc123 观察四个步骤的执行进度 等待图谱构建完成(约1-5分钟) ``` **步骤5**: 完成 ``` 所有步骤显示"已完成" 左侧展示图谱节点和关系统计 ``` ## 技术细节 ### API重试机制 ```javascript export const requestWithRetry = async ( requestFn, maxRetries = 3, delay = 1000 ) => { for (let i = 0; i < maxRetries; i++) { try { return await requestFn() } catch (error) { if (i === maxRetries - 1) throw error const waitTime = delay * Math.pow(2, i) await new Promise(resolve => setTimeout(resolve, waitTime)) } } } ``` ### 文件上传处理 ```javascript // 构建FormData const formDataObj = new FormData() // 添加文件 files.value.forEach(file => { formDataObj.append('files', file) }) // 添加文本字段 formDataObj.append('simulation_requirement', requirement) ``` ### 轮询实现 ```javascript let pollTimer = setInterval(async () => { const response = await getTaskStatus(taskId) if (response.data.status === 'completed') { clearInterval(pollTimer) // 处理完成逻辑 } }, 2000) // 组件卸载时清理 onUnmounted(() => { if (pollTimer) clearInterval(pollTimer) }) ``` ## 常见问题 ### Q: 上传文件后看不到文件列表? A: 检查文件格式是否支持(PDF、MD、TXT),不支持的格式会被自动过滤 ### Q: 点击"开始模拟"没有反应? A: 检查是否填写了模拟需求和上传了文件,两者都是必填项 ### Q: 页面一直显示"处理中"? A: 1. 检查后端服务是否正常运行 2. 查看浏览器控制台是否有错误信息 3. 检查网络连接 ### Q: 图谱构建一直不完成? A: 1. 图谱构建可能需要1-5分钟,请耐心等待 2. 查看右侧进度信息 3. 如果超过10分钟,可能是后端处理失败,查看后端日志 ## 性能优化建议 1. **大文件上传**: 建议单个文件不超过10MB 2. **网络优化**: 使用稳定的网络连接 3. **浏览器**: 推荐使用Chrome浏览器 4. **并发限制**: 避免同时打开多个模拟任务 --- **文档更新**: 2025-12-10 **版本**: v1.0.0