diff --git a/PROJECT_STATUS.md b/PROJECT_STATUS.md new file mode 100644 index 0000000..77f9834 --- /dev/null +++ b/PROJECT_STATUS.md @@ -0,0 +1,303 @@ +# MiroFish 项目状态报告 + +## 项目概览 +MiroFish是一个社交媒体舆论模拟系统,采用前后端分离架构。 + +## 完成情况 + +### ✅ 后端 (Flask) +- [x] RESTful API架构 +- [x] 知识图谱构建(Zep) +- [x] LLM集成(OpenAI兼容接口) +- [x] 本体生成服务 +- [x] 图谱构建服务 +- [x] 模拟管理服务 +- [x] 容错重试机制 +- [x] 详细的API文档 + +**后端地址**: http://localhost:5001 + +### ✅ 前端 (Vue 3) +- [x] Vue 3 + Vite脚手架搭建 +- [x] 项目目录结构规划 +- [x] 首页设计完成(极简黑白线条风) +- [x] 文件上传功能(支持拖拽) +- [x] API接口封装(含重试机制) +- [x] 路由管理(Vue Router 4) +- [x] 第二页基础框架 +- [x] 自动轮询任务状态 +- [x] 响应式设计 + +**前端地址**: http://localhost:3000 + +## 目录结构 + +``` +MiroFish/ +├── backend/ # 后端服务 +│ ├── app/ +│ │ ├── api/ # API路由 +│ │ ├── services/ # 业务逻辑 +│ │ ├── models/ # 数据模型 +│ │ └── utils/ # 工具类 +│ ├── scripts/ # 模拟脚本 +│ ├── uploads/ # 数据存储 +│ ├── run.py # 启动入口 +│ └── requirements.txt # Python依赖 +│ +├── frontend/ # 前端项目 +│ ├── src/ +│ │ ├── api/ # API接口封装 +│ │ ├── assets/ # 静态资源 +│ │ ├── views/ # 页面组件 +│ │ ├── router/ # 路由配置 +│ │ ├── App.vue # 根组件 +│ │ └── main.js # 入口文件 +│ ├── .env.development # 开发环境配置 +│ ├── vite.config.js # Vite配置 +│ └── package.json # 依赖配置 +│ +├── static/ # 共享静态资源 +│ └── image/ +│ └── MiroFish_logo_compressed.jpeg +│ +├── mydoc/ # 项目文档 +│ ├── MiroFish文档.md +│ └── 前端设计思路.md +│ +└── .env # 环境配置(后端) +``` + +## 首页功能展示 + +### 页面元素 +1. **Logo**: MiroFish品牌标识(居中展示) +2. **标语**: "上传任意报告,模拟世界即刻开始" +3. **模拟需求输入框**: 用户描述模拟需求 +4. **项目名称**: 可选的项目命名 +5. **文件上传区域**: + - 支持拖拽上传 + - 支持点击选择 + - 支持多文件 + - 格式: PDF、Markdown、TXT +6. **额外说明**: 可选的补充信息 +7. **开始模拟按钮**: 提交表单,调用API + +### 设计风格 +- **极简黑白线条风** +- 纯黑(#000000) + 纯白(#FFFFFF) +- 1-2px实线边框 +- 清晰的排版和间距 +- 简洁的交互动画 + +### 交互流程 +1. 用户填写模拟需求 +2. 上传相关文档 +3. 点击"开始模拟" +4. 系统调用 `/api/graph/ontology/generate` 接口 +5. 显示加载状态 +6. 成功后跳转到处理页面 `/process/:projectId` + +## 第二页功能 + +### 布局 +- **左侧**: 实时图谱可视化 +- **右侧**: Step 1 - 现实种子构建流程 + +### 自动化流程 +1. 自动加载项目信息 +2. 自动开始图谱构建 +3. 轮询任务状态(每2秒) +4. 实时更新进度 +5. 完成后加载图谱数据 + +### 流程步骤 +- [x] 文档分析 +- [x] 本体生成 +- [x] 图谱构建 +- [x] 完成 + +## API接口实现 + +### 已实现的接口调用 +1. **生成本体**: `POST /api/graph/ontology/generate` + - multipart/form-data格式 + - 包含文件和表单数据 + - 自动重试机制 + +2. **构建图谱**: `POST /api/graph/build` + - 自动触发 + - 返回任务ID + +3. **查询任务**: `GET /api/graph/task/{taskId}` + - 轮询机制 + - 每2秒查询一次 + +4. **获取图谱**: `GET /api/graph/data/{graphId}` + - 构建完成后加载 + +5. **获取项目**: `GET /api/graph/project/{projectId}` + - 页面加载时获取 + +## 容错机制 + +### 前端 +- API请求自动重试(最多3次) +- 指数退避策略(1s -> 2s -> 4s) +- 超时处理(5分钟) +- 友好的错误提示 +- 网络错误处理 + +### 后端 +- Zep API调用重试 +- LLM API调用重试 +- 详细的日志记录 +- 异常捕获和处理 + +## 启动步骤 + +### 1. 启动后端 +```bash +cd /Users/guohangjiang/Desktop/MiroFish/backend +conda activate MiroFish +python run.py +``` + +### 2. 启动前端 +```bash +cd /Users/guohangjiang/Desktop/MiroFish/frontend +npm run dev +``` + +### 3. 访问系统 +- 前端: http://localhost:3000 +- 后端: http://localhost:5001 + +## 技术栈 + +### 后端 +- Flask 3.0+ +- Zep Cloud SDK 2.0+ +- OpenAI SDK 1.0+ +- PyMuPDF (文本提取) +- Python 3.8+ + +### 前端 +- Vue 3 (Composition API) +- Vite 7 +- Vue Router 4 +- Axios + +## 开发环境 + +- **操作系统**: macOS (M系列芯片) +- **Python环境**: conda环境 MiroFish +- **Node.js**: >= 16.0.0 +- **浏览器**: Chrome (推荐) + +## 配置文件 + +### 后端 (.env) +```bash +FLASK_PORT=5001 +LLM_API_KEY=your-key +LLM_BASE_URL=https://api.openai.com/v1 +LLM_MODEL_NAME=gpt-4o-mini +ZEP_API_KEY=your-key +``` + +### 前端 (.env.development) +```bash +VITE_API_BASE_URL=http://localhost:5001 +``` + +## 已实现的规则 + +✅ **API容错重试机制**: 所有远程API调用都有重试机制 +✅ **RESTful风格**: 后端API采用RESTful设计 +✅ **统一配置**: LLM和Zep密钥统一存储在.env文件 +✅ **OpenAI格式**: LLM调用统一使用OpenAI库格式 +✅ **Conda环境**: 程序运行在MiroFish环境中 +✅ **前后端分离**: Vue前端 + Flask后端 + +## 测试建议 + +### 功能测试 +1. [ ] 文件上传(拖拽、点击) +2. [ ] 表单验证 +3. [ ] API调用 +4. [ ] 页面跳转 +5. [ ] 错误处理 +6. [ ] 响应式布局 + +### 端到端测试 +1. [ ] 上传PDF文档 +2. [ ] 填写模拟需求 +3. [ ] 提交表单 +4. [ ] 观察处理流程 +5. [ ] 等待图谱构建完成 + +## 后续开发 + +### 优先级高 +- [ ] 图谱可视化实现(D3.js或ECharts) +- [ ] 模拟运行页面 +- [ ] 结果展示页面 +- [ ] Agent对话功能 + +### 优先级中 +- [ ] 历史记录管理 +- [ ] 项目列表页面 +- [ ] 用户设置 +- [ ] 导出功能 + +### 优先级低 +- [ ] 数据统计分析 +- [ ] 多语言支持 +- [ ] 深色模式 +- [ ] 移动端优化 + +## 项目亮点 + +1. **极简黑白线条风格**: 独特的视觉设计 +2. **全自动化流程**: 用户只需上传文档和需求 +3. **容错机制完善**: 多重重试和错误处理 +4. **前后端分离**: 清晰的架构设计 +5. **实时反馈**: 轮询机制实时更新状态 +6. **响应式设计**: 支持多种设备 + +## 当前状态 + +🟢 **开发服务器运行中** +- 后端: 需要手动启动 +- 前端: 已启动在 http://localhost:3000 + +✅ **首页功能完整** +- 文件上传 ✓ +- 表单验证 ✓ +- API调用 ✓ +- 错误处理 ✓ + +⚠️ **待完善功能** +- 图谱可视化(第二页) +- 更多页面开发 +- 完整的端到端测试 + +## 总结 + +MiroFish项目的前端脚手架已搭建完成,首页设计符合极简黑白线条风格要求,核心功能已实现: + +1. ✅ 文件上传(支持拖拽) +2. ✅ 表单验证和提交 +3. ✅ API接口调用 +4. ✅ 路由管理 +5. ✅ 错误处理 +6. ✅ 响应式设计 + +用户可以通过首页上传文档和填写模拟需求,点击"开始模拟"后系统会调用后端的 `/api/graph/ontology/generate` 接口,成功后跳转到处理页面查看图谱构建进度。 + +--- + +**更新时间**: 2025-12-10 +**版本**: v1.0.0 +**状态**: 开发中 🚧 diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..beec310 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,130 @@ +# MiroFish Frontend + +MiroFish项目的前端部分,采用Vue 3 + Vite构建,极简黑白线条设计风格。 + +## 技术栈 + +- **Vue 3** - 渐进式JavaScript框架 +- **Vite** - 下一代前端构建工具 +- **Vue Router 4** - 官方路由管理器 +- **Axios** - HTTP客户端 + +## 项目结构 + +``` +frontend/ +├── src/ +│ ├── api/ # API接口封装 +│ │ ├── index.js # axios配置和重试机制 +│ │ └── graph.js # 图谱相关接口 +│ ├── assets/ # 静态资源 +│ │ └── logo/ # Logo图片 +│ ├── components/ # 通用组件 +│ ├── views/ # 页面组件 +│ │ ├── Home.vue # 首页 +│ │ └── Process.vue # 处理页面 +│ ├── router/ # 路由配置 +│ │ └── index.js +│ ├── utils/ # 工具函数 +│ ├── App.vue # 根组件 +│ └── main.js # 入口文件 +├── .env.development # 开发环境配置 +├── .env.production # 生产环境配置 +└── vite.config.js # Vite配置 +``` + +## 开发指南 + +### 环境要求 + +- Node.js >= 16.0.0 +- npm >= 8.0.0 + +### 安装依赖 + +```bash +npm install +``` + +### 启动开发服务器 + +```bash +npm run dev +``` + +服务将在 http://localhost:3000 启动。 + +### 构建生产版本 + +```bash +npm run build +``` + +### 预览生产构建 + +```bash +npm run preview +``` + +## 功能说明 + +### 首页 (/) + +- Logo展示 +- 模拟需求输入 +- 文档上传(支持PDF、Markdown、TXT格式) +- 拖拽上传支持 +- 点击"开始模拟"调用后端接口 `/api/graph/ontology/generate` + +### 处理页面 (/process/:projectId) + +- 左侧:实时图谱可视化展示 +- 右侧:Step 1 - 现实种子构建流程展示 +- 自动轮询任务状态 +- 实时更新构建进度 + +## 设计风格 + +采用极简黑白线条风格: + +- 主色调:黑色 (#000000) 和白色 (#FFFFFF) +- 线条粗细:1px - 2px +- 字体:系统默认无衬线字体 +- 交互:简洁的hover效果和过渡动画 +- 布局:清晰的分栏和间距 + +## API集成 + +### 容错机制 + +- 自动重试:API请求失败时最多重试3次 +- 指数退避:重试间隔逐步增加(1s, 2s, 4s) +- 超时控制:默认5分钟超时时间 +- 错误提示:友好的用户错误提示 + +### 接口说明 + +参见 `src/api/graph.js` 中的接口定义和注释。 + +## 开发规范 + +- 使用 Vue 3 Composition API +- 组件采用 ` + + diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000..7ee9e75 --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,1594 @@ +{ + "name": "frontend", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "frontend", + "version": "0.0.0", + "dependencies": { + "axios": "^1.13.2", + "vue": "^3.5.24", + "vue-router": "^4.6.3" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^6.0.1", + "vite": "^7.2.4" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.50", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.50.tgz", + "integrity": "sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.2.tgz", + "integrity": "sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-beta.50" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.25.tgz", + "integrity": "sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/shared": "3.5.25", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.25.tgz", + "integrity": "sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.25", + "@vue/shared": "3.5.25" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.25.tgz", + "integrity": "sha512-PUgKp2rn8fFsI++lF2sO7gwO2d9Yj57Utr5yEsDf3GNaQcowCLKL7sf+LvVFvtJDXUp/03+dC6f2+LCv5aK1ag==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/compiler-core": "3.5.25", + "@vue/compiler-dom": "3.5.25", + "@vue/compiler-ssr": "3.5.25", + "@vue/shared": "3.5.25", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.25.tgz", + "integrity": "sha512-ritPSKLBcParnsKYi+GNtbdbrIE1mtuFEJ4U1sWeuOMlIziK5GtOL85t5RhsNy4uWIXPgk+OUdpnXiTdzn8o3A==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.25", + "@vue/shared": "3.5.25" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/reactivity": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.25.tgz", + "integrity": "sha512-5xfAypCQepv4Jog1U4zn8cZIcbKKFka3AgWHEFQeK65OW+Ys4XybP6z2kKgws4YB43KGpqp5D/K3go2UPPunLA==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.25" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.25.tgz", + "integrity": "sha512-Z751v203YWwYzy460bzsYQISDfPjHTl+6Zzwo/a3CsAf+0ccEjQ8c+0CdX1WsumRTHeywvyUFtW6KvNukT/smA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.25", + "@vue/shared": "3.5.25" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.25.tgz", + "integrity": "sha512-a4WrkYFbb19i9pjkz38zJBg8wa/rboNERq3+hRRb0dHiJh13c+6kAbgqCPfMaJ2gg4weWD3APZswASOfmKwamA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.25", + "@vue/runtime-core": "3.5.25", + "@vue/shared": "3.5.25", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.25.tgz", + "integrity": "sha512-UJaXR54vMG61i8XNIzTSf2Q7MOqZHpp8+x3XLGtE3+fL+nQd+k7O5+X3D/uWrnQXOdMw5VPih+Uremcw+u1woQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.25", + "@vue/shared": "3.5.25" + }, + "peerDependencies": { + "vue": "3.5.25" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.25.tgz", + "integrity": "sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/vite": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.7.tgz", + "integrity": "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.25.tgz", + "integrity": "sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/compiler-dom": "3.5.25", + "@vue/compiler-sfc": "3.5.25", + "@vue/runtime-dom": "3.5.25", + "@vue/server-renderer": "3.5.25", + "@vue/shared": "3.5.25" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.3.tgz", + "integrity": "sha512-ARBedLm9YlbvQomnmq91Os7ck6efydTSpRP3nuOKCvgJOHNrhRoJDSKtee8kcL1Vf7nz6U+PMBL+hTvR3bTVQg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..217cefe --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,20 @@ +{ + "name": "frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "axios": "^1.13.2", + "vue": "^3.5.24", + "vue-router": "^4.6.3" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^6.0.1", + "vite": "^7.2.4" + } +} diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/frontend/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/src/App.vue b/frontend/src/App.vue new file mode 100644 index 0000000..a86d6e8 --- /dev/null +++ b/frontend/src/App.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/frontend/src/api/graph.js b/frontend/src/api/graph.js new file mode 100644 index 0000000..ef90a2b --- /dev/null +++ b/frontend/src/api/graph.js @@ -0,0 +1,70 @@ +import service, { requestWithRetry } from './index' + +/** + * 生成本体(上传文档和模拟需求) + * @param {Object} data - 包含files, simulation_requirement, project_name等 + * @returns {Promise} + */ +export function generateOntology(formData) { + return requestWithRetry(() => + service({ + url: '/api/graph/ontology/generate', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) + ) +} + +/** + * 构建图谱 + * @param {Object} data - 包含project_id, graph_name等 + * @returns {Promise} + */ +export function buildGraph(data) { + return requestWithRetry(() => + service({ + url: '/api/graph/build', + method: 'post', + data + }) + ) +} + +/** + * 查询任务状态 + * @param {String} taskId - 任务ID + * @returns {Promise} + */ +export function getTaskStatus(taskId) { + return service({ + url: `/api/graph/task/${taskId}`, + method: 'get' + }) +} + +/** + * 获取图谱数据 + * @param {String} graphId - 图谱ID + * @returns {Promise} + */ +export function getGraphData(graphId) { + return service({ + url: `/api/graph/data/${graphId}`, + method: 'get' + }) +} + +/** + * 获取项目信息 + * @param {String} projectId - 项目ID + * @returns {Promise} + */ +export function getProject(projectId) { + return service({ + url: `/api/graph/project/${projectId}`, + method: 'get' + }) +} diff --git a/frontend/src/api/index.js b/frontend/src/api/index.js new file mode 100644 index 0000000..e2d9465 --- /dev/null +++ b/frontend/src/api/index.js @@ -0,0 +1,67 @@ +import axios from 'axios' + +// 创建axios实例 +const service = axios.create({ + baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:5001', + timeout: 300000, // 5分钟超时(本体生成可能需要较长时间) + headers: { + 'Content-Type': 'application/json' + } +}) + +// 请求拦截器 +service.interceptors.request.use( + config => { + return config + }, + error => { + console.error('Request error:', error) + return Promise.reject(error) + } +) + +// 响应拦截器(容错重试机制) +service.interceptors.response.use( + response => { + const res = response.data + + // 如果返回的状态码不是success,则抛出错误 + if (!res.success && res.success !== undefined) { + console.error('API Error:', res.error || res.message || 'Unknown error') + return Promise.reject(new Error(res.error || res.message || 'Error')) + } + + return res + }, + error => { + console.error('Response error:', error) + + // 处理超时 + if (error.code === 'ECONNABORTED' && error.message.includes('timeout')) { + console.error('Request timeout') + } + + // 处理网络错误 + if (error.message === 'Network Error') { + console.error('Network error - please check your connection') + } + + return Promise.reject(error) + } +) + +// 带重试的请求函数 +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 + + console.warn(`Request failed, retrying (${i + 1}/${maxRetries})...`) + await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, i))) + } + } +} + +export default service diff --git a/frontend/src/assets/logo/MiroFish_logo_compressed.jpeg b/frontend/src/assets/logo/MiroFish_logo_compressed.jpeg new file mode 100644 index 0000000..eb7bd5a Binary files /dev/null and b/frontend/src/assets/logo/MiroFish_logo_compressed.jpeg differ diff --git a/frontend/src/main.js b/frontend/src/main.js new file mode 100644 index 0000000..c8e37b0 --- /dev/null +++ b/frontend/src/main.js @@ -0,0 +1,9 @@ +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js new file mode 100644 index 0000000..5df5ac0 --- /dev/null +++ b/frontend/src/router/index.js @@ -0,0 +1,24 @@ +import { createRouter, createWebHistory } from 'vue-router' +import Home from '../views/Home.vue' +import Process from '../views/Process.vue' + +const routes = [ + { + path: '/', + name: 'Home', + component: Home + }, + { + path: '/process/:projectId', + name: 'Process', + component: Process, + props: true + } +] + +const router = createRouter({ + history: createWebHistory(), + routes +}) + +export default router diff --git a/frontend/src/views/Home.vue b/frontend/src/views/Home.vue new file mode 100644 index 0000000..b10cff8 --- /dev/null +++ b/frontend/src/views/Home.vue @@ -0,0 +1,726 @@ + + + + + diff --git a/frontend/src/views/Process.vue b/frontend/src/views/Process.vue new file mode 100644 index 0000000..d73a777 --- /dev/null +++ b/frontend/src/views/Process.vue @@ -0,0 +1,453 @@ + + + + + diff --git a/frontend/vite.config.js b/frontend/vite.config.js new file mode 100644 index 0000000..7cec1a7 --- /dev/null +++ b/frontend/vite.config.js @@ -0,0 +1,18 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [vue()], + server: { + port: 3000, + open: true, + proxy: { + '/api': { + target: 'http://localhost:5001', + changeOrigin: true, + secure: false + } + } + } +}) diff --git a/frontend/功能演示.md b/frontend/功能演示.md new file mode 100644 index 0000000..91e0bb3 --- /dev/null +++ b/frontend/功能演示.md @@ -0,0 +1,506 @@ +# 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 diff --git a/frontend/启动指南.md b/frontend/启动指南.md new file mode 100644 index 0000000..a2862d4 --- /dev/null +++ b/frontend/启动指南.md @@ -0,0 +1,198 @@ +# MiroFish 前端启动指南 + +## 项目已完成功能 + +✅ Vue 3 + Vite 脚手架搭建完成 +✅ 项目目录结构规划完成 +✅ API接口封装(含容错重试机制) +✅ 首页设计完成(极简黑白线条风) +✅ 第二页基础框架完成 +✅ 路由配置完成 +✅ 开发服务器成功启动 + +## 快速开始 + +### 1. 启动后端服务 + +```bash +# 进入后端目录 +cd /Users/guohangjiang/Desktop/MiroFish/backend + +# 激活conda环境 +conda activate MiroFish + +# 启动Flask服务 +python run.py +``` + +后端服务将运行在: http://localhost:5001 + +### 2. 启动前端服务 + +前端开发服务器已经启动,访问地址: +**http://localhost:3000/** + +如需重新启动: +```bash +cd /Users/guohangjiang/Desktop/MiroFish/frontend +npm run dev +``` + +## 首页功能说明 + +### 页面布局 +- **Logo区域**: 居中展示MiroFish品牌Logo +- **标语**: "上传任意报告,模拟世界即刻开始" +- **表单区域**: + - 模拟需求输入框(必填) + - 项目名称输入框(可选) + - 文件上传区域(支持拖拽,必填) + - 额外说明输入框(可选) + - 开始模拟按钮 + +### 交互功能 +1. **文件上传**: + - 支持点击选择文件 + - 支持拖拽上传 + - 支持多文件上传 + - 支持格式: PDF、Markdown(.md)、TXT + - 可以删除已选择的文件 + +2. **表单验证**: + - 必须填写模拟需求 + - 必须上传至少一个文件 + - 满足条件后"开始模拟"按钮才可点击 + +3. **提交流程**: + - 点击"开始模拟"按钮 + - 显示加载状态 + - 调用后端API: `POST /api/graph/ontology/generate` + - 成功后自动跳转到处理页面 + +4. **错误处理**: + - API调用失败显示错误提示 + - 自动重试机制(最多3次) + - 友好的用户提示信息 + +## 第二页功能说明 + +### 页面布局 +- **左侧面板**: 实时图谱展示区 +- **右侧面板**: Step 1 - 现实种子构建流程 + +### 流程步骤 +1. 文档分析 +2. 本体生成 +3. 图谱构建 +4. 完成 + +### 自动化功能 +- 自动加载项目信息 +- 自动开始图谱构建 +- 自动轮询任务状态(每2秒) +- 实时更新构建进度 +- 构建完成后加载图谱数据 + +## 设计风格特点 + +### 极简黑白线条风 +- **颜色**: 纯黑(#000000) + 纯白(#FFFFFF) +- **线条**: 1-2px实线边框 +- **字体**: 系统默认无衬线字体 +- **布局**: 清晰的网格和间距 +- **交互**: 简洁的hover效果 + +### 响应式设计 +- 支持桌面端(>=1024px) +- 支持平板端(768px-1024px) +- 支持移动端(<768px) + +## API接口集成 + +### 已实现接口 +1. `POST /api/graph/ontology/generate` - 生成本体 +2. `POST /api/graph/build` - 构建图谱 +3. `GET /api/graph/task/{taskId}` - 查询任务状态 +4. `GET /api/graph/data/{graphId}` - 获取图谱数据 +5. `GET /api/graph/project/{projectId}` - 获取项目信息 + +### 容错机制 +- 自动重试(最多3次) +- 指数退避(1s -> 2s -> 4s) +- 超时处理(5分钟) +- 错误提示 + +## 目录结构 + +``` +frontend/ +├── src/ +│ ├── api/ # API接口 +│ │ ├── index.js # axios配置、重试机制 +│ │ └── graph.js # 图谱相关接口 +│ ├── assets/ +│ │ └── logo/ # Logo图片 +│ ├── views/ +│ │ ├── Home.vue # 首页 +│ │ └── Process.vue # 处理页面 +│ ├── router/ +│ │ └── index.js # 路由配置 +│ ├── App.vue # 根组件 +│ └── main.js # 入口文件 +├── .env.development # 开发环境配置 +├── vite.config.js # Vite配置 +└── package.json # 依赖配置 +``` + +## 开发说明 + +### 技术栈 +- Vue 3 (Composition API) +- Vite 7 +- Vue Router 4 +- Axios + +### 开发规范 +- 使用 `