diff --git a/README.md b/README.md index f0e7dd1..ca40fce 100644 --- a/README.md +++ b/README.md @@ -1 +1,126 @@ -OJ next \ No newline at end of file +# OJ Next + +基于 Vue 3 + TypeScript 的在线判题系统前端项目。 + +## 项目特性 + +- 🎯 **现代化技术栈** - Vue 3 + TypeScript + Vite +- 📊 **数据可视化** - 丰富的图表和统计功能 +- 🎨 **流程图编辑器** - 内置 FlowchartEditor 组件 +- 📱 **响应式设计** - 支持多端适配 +- ⚡ **高性能** - 优化的组件和状态管理 + +## 核心组件 + +### FlowchartEditor 流程图编辑器 + +一个功能完整的流程图编辑器组件,支持: + +- 🎯 **拖拽创建节点** - 从工具栏拖拽节点到画布 +- 🔗 **节点连接** - 支持节点间的连线操作 +- ✏️ **节点编辑** - 双击节点进行文本编辑 +- 📋 **节点操作** - 复制、删除、批量操作 +- ↩️ **撤销重做** - 完整的历史记录管理 +- ⌨️ **键盘快捷键** - Ctrl+Z/Ctrl+Y 撤销重做,Delete 删除 +- 💾 **自动保存** - 本地缓存,防止数据丢失 +- 🎨 **多种节点类型** - 开始、输入、处理、判断、循环、输出、结束 +- 🖱️ **交互优化** - 流畅的拖拽体验和视觉反馈 + +**核心特性**: +- 基于 Vue Flow 构建,性能优异 +- 模块化设计,易于扩展 +- 响应式布局,支持多端适配 +- 完整的 TypeScript 支持 + +详细文档:[FlowchartEditor 文档](./docs/FlowchartEditor.md) + +## 技术栈 + +- **Vue 3** - 渐进式 JavaScript 框架 +- **TypeScript** - JavaScript 的超集 +- **Rsbuild** - 基于 Rspack 的构建工具 +- **Vue Flow** - 流程图组件库 +- **Composition API** - Vue 3 组合式 API +- **Naive UI** - Vue 3 组件库 +- **Chart.js** - 图表可视化库 +- **CodeMirror** - 代码编辑器 +- **Yjs** - 实时协作框架 + +## 项目结构 + +``` +src/ +├── shared/ # 共享组件和工具 +│ ├── components/ +│ │ └── FlowchartEditor/ # 流程图编辑器 +│ │ ├── index.vue # 主组件 +│ │ ├── CustomNode.vue # 自定义节点 +│ │ ├── Toolbar.vue # 工具栏 +│ │ ├── NodeHandles.vue # 节点操作 +│ │ ├── NodeActions.vue # 节点动作 +│ │ ├── useCache.ts # 缓存管理 +│ │ ├── useDnD.ts # 拖拽处理 +│ │ ├── useFlowOperations.ts # 流程操作 +│ │ ├── useHistory.ts # 历史记录 +│ │ └── useNodeStyles.ts # 节点样式 +│ ├── composables/ # 组合式函数 +│ ├── layout/ # 布局组件 +│ ├── store/ # 状态管理 +│ └── themes/ # 主题配置 +├── oj/ # 主要业务组件 +│ ├── ai/ # AI分析模块 +│ ├── problem/ # 题目相关 +│ ├── contest/ # 竞赛相关 +│ ├── submission/ # 提交相关 +│ └── store/ # 业务状态管理 +├── admin/ # 管理后台组件 +└── utils/ # 工具函数 +``` + +## 开发指南 + +### 安装依赖 + +```bash +npm install +``` + +### 启动开发服务器 + +```bash +npm start +# 或 +npm run start +``` + +### 构建生产版本 + +```bash +npm run build +``` + +### 构建测试环境版本 + +```bash +npm run build:test +``` + +### 构建预发布版本 + +```bash +npm run build:staging +``` + +## 文档 + +- [FlowchartEditor 流程图编辑器](./docs/FlowchartEditor.md) +- [图表组件说明](./docs/图表.md) +- [API 接口对比分析](./docs/API接口对比分析.md) + +## 贡献 + +欢迎提交 Issue 和 Pull Request! + +## 许可证 + +MIT License \ No newline at end of file diff --git a/docs/API接口对比分析.md b/docs/API接口对比分析.md index 096f37e..2a0cb71 100644 --- a/docs/API接口对比分析.md +++ b/docs/API接口对比分析.md @@ -2,7 +2,23 @@ ## 更新日志 -### 最近更新(2025-10) +### 最近更新(2025-01-15) +- ✨ **FlowchartEditor 流程图编辑器**:新增完整的流程图编辑功能 + - 基于 Vue Flow 构建的流程图编辑器组件 + - 支持7种节点类型:开始、输入、处理、判断、循环、输出、结束 + - 完整的拖拽创建、节点连接、编辑功能 + - 撤销重做、自动保存、键盘快捷键支持 + - 模块化设计,包含9个独立的功能模块 +- 🎨 **前端组件优化**:完善了组件文档和项目结构说明 + - 更新了 README.md 中的技术栈和项目结构 + - 创建了详细的 FlowchartEditor 使用文档 + - 优化了开发指南和构建流程说明 +- 🔧 **构建工具升级**:从 Vite 迁移到 Rsbuild + - 使用 Rsbuild 作为新的构建工具 + - 支持多环境构建(test、staging、production) + - 优化了构建性能和开发体验 + +### 历史更新(2025-10) - ✨ **AI分析功能增强**:完善了AI智能分析模块的文档说明 - 详细说明了4个AI相关接口的功能和参数 - 新增等级系统说明(S/A/B/C),包含特殊规则 @@ -434,3 +450,99 @@ const hasTriedButNotPassed = computed(() => { **结论**: 此接口是系统内部通信接口,前端完全不需要调用。类似的内部接口还可能存在于分布式系统的其他服务间通信中。 +--- + +## 六、新增功能模块 + +### FlowchartEditor 流程图编辑器 ✨ + +**功能概述**: 基于 Vue Flow 构建的完整流程图编辑器,支持拖拽创建、节点连接、编辑等核心功能。 + +**技术实现**: +- **核心库**: Vue Flow (@vue-flow/core) +- **组件架构**: 模块化设计,9个独立功能模块 +- **状态管理**: 基于 Vue 3 Composition API +- **数据持久化**: localStorage 自动缓存 +- **交互体验**: 拖拽、键盘快捷键、撤销重做 + +**组件结构**: +``` +FlowchartEditor/ +├── index.vue # 主组件 - 整合所有功能 +├── CustomNode.vue # 自定义节点 - 7种节点类型 +├── Toolbar.vue # 工具栏 - 节点创建和操作 +├── NodeHandles.vue # 节点操作手柄 - 连接点管理 +├── NodeActions.vue # 节点动作 - 删除、编辑按钮 +├── useCache.ts # 缓存管理 - 自动保存/恢复 +├── useDnD.ts # 拖拽处理 - 节点创建逻辑 +├── useFlowOperations.ts # 流程操作 - 增删改查 +├── useHistory.ts # 历史记录 - 撤销重做 +└── useNodeStyles.ts # 节点样式 - 类型配置 +``` + +**节点类型支持**: +- **开始节点** (start) - 流程开始,绿色主题 +- **输入节点** (input) - 数据输入,蓝色主题 +- **处理节点** (default) - 数据处理,紫色主题 +- **判断节点** (decision) - 条件判断,橙色主题 +- **循环节点** (loop) - 循环处理,青色主题 +- **输出节点** (output) - 数据输出,粉色主题 +- **结束节点** (end) - 流程结束,红色主题 + +**核心功能**: +1. **拖拽创建**: 从工具栏拖拽节点到画布 +2. **节点连接**: 支持节点间的连线操作 +3. **节点编辑**: 双击节点进行文本编辑 +4. **撤销重做**: 完整的历史记录管理 +5. **自动保存**: 本地缓存,防止数据丢失 +6. **键盘快捷键**: Ctrl+Z/Ctrl+Y 撤销重做,Delete 删除 +7. **批量操作**: 支持多选和批量删除 + +**数据格式**: +```typescript +// 节点数据 +interface Node { + id: string + type: string + position: { x: number, y: number } + data: { + customLabel: string + [key: string]: any + } +} + +// 边数据 +interface Edge { + id: string + source: string + target: string + sourceHandle?: string + targetHandle?: string + type?: string +} +``` + +**使用场景**: +- 算法流程图绘制 +- 业务流程设计 +- 教学演示工具 +- 问题分析图表 + +**性能优化**: +- 基于 Vue Flow 的高性能渲染 +- 模块化设计,按需加载 +- 本地缓存减少重复计算 +- 响应式状态管理 + +**扩展性**: +- 支持自定义节点类型 +- 可扩展工具栏功能 +- 支持主题定制 +- 支持数据导入导出 + +**文档支持**: +- 详细的使用文档: `docs/FlowchartEditor.md` +- 完整的 API 说明 +- 最佳实践指南 +- 故障排除手册 + diff --git a/docs/FlowchartEditor.md b/docs/FlowchartEditor.md new file mode 100644 index 0000000..e026d3a --- /dev/null +++ b/docs/FlowchartEditor.md @@ -0,0 +1,311 @@ +# FlowchartEditor 流程图编辑器 + +一个基于 Vue 3 + Vue Flow 构建的功能完整的流程图编辑器组件。 + +## 功能特性 + +### 🎯 核心功能 +- **拖拽创建节点** - 从工具栏拖拽节点到画布 +- **节点连接** - 支持节点间的连线操作 +- **节点编辑** - 双击节点进行文本编辑 +- **撤销重做** - 完整的历史记录管理 +- **自动保存** - 本地缓存,防止数据丢失 +- **键盘快捷键** - 支持常用快捷键操作 + +### 🎨 节点类型 +- **开始节点** (start) - 流程开始 +- **输入节点** (input) - 数据输入 +- **处理节点** (default) - 数据处理 +- **判断节点** (decision) - 条件判断 +- **循环节点** (loop) - 循环处理 +- **输出节点** (output) - 数据输出 +- **结束节点** (end) - 流程结束 + +### ⌨️ 快捷键 +- `Ctrl+Z` / `Cmd+Z` - 撤销 +- `Ctrl+Y` / `Cmd+Shift+Z` - 重做 +- `Delete` / `Backspace` - 删除选中节点 + +## 组件结构 + +``` +FlowchartEditor/ +├── index.vue # 主组件 +├── CustomNode.vue # 自定义节点组件 +├── Toolbar.vue # 工具栏组件 +├── NodeHandles.vue # 节点操作手柄 +├── NodeActions.vue # 节点动作按钮 +├── useCache.ts # 缓存管理 +├── useDnD.ts # 拖拽处理 +├── useFlowOperations.ts # 流程操作 +├── useHistory.ts # 历史记录 +└── useNodeStyles.ts # 节点样式 +``` + +## 使用方法 + +### 基本用法 + +```vue + + + +``` + +### 获取流程图数据 + +```javascript +// 获取当前流程图数据 +const data = flowchartRef.value.getFlowchartData() +console.log(data.nodes) // 节点数组 +console.log(data.edges) // 边数组 +``` + +## 组件详解 + +### 主组件 (index.vue) + +主组件负责整合所有功能模块,提供完整的流程图编辑体验。 + +**主要功能**: +- 整合 Vue Flow 核心功能 +- 管理节点和边的状态 +- 处理用户交互事件 +- 提供数据暴露接口 + +**暴露的方法**: +- `getFlowchartData()` - 获取当前流程图数据 + +### 自定义节点 (CustomNode.vue) + +基于 Vue Flow 的自定义节点组件,支持多种节点类型。 + +**节点类型配置**: +- 每种节点类型都有独特的样式和图标 +- 支持自定义标签文本 +- 提供删除和编辑功能 + +### 工具栏 (Toolbar.vue) + +提供节点创建和操作的工具集合。 + +**功能**: +- 节点类型选择 +- 撤销/重做操作 +- 清空画布 +- 保存状态显示 + +### 缓存管理 (useCache.ts) + +提供本地存储功能,防止数据丢失。 + +**功能**: +- 自动保存到 localStorage +- 页面刷新后恢复数据 +- 保存状态提示 +- 清空缓存功能 + +### 拖拽处理 (useDnD.ts) + +处理节点拖拽创建的逻辑。 + +**功能**: +- 拖拽开始处理 +- 拖拽悬停效果 +- 拖拽放置处理 +- 节点位置计算 + +### 流程操作 (useFlowOperations.ts) + +处理流程图的增删改操作。 + +**功能**: +- 节点连接处理 +- 边删除处理 +- 节点删除处理 +- 节点更新处理 +- 清空画布 + +### 历史记录 (useHistory.ts) + +提供撤销重做功能。 + +**功能**: +- 状态快照保存 +- 撤销操作 +- 重做操作 +- 历史记录管理 + +### 节点样式 (useNodeStyles.ts) + +定义各种节点类型的样式配置。 + +**功能**: +- 节点类型配置 +- 样式定义 +- 图标配置 +- 颜色主题 + +## 样式定制 + +### 节点样式 + +可以通过修改 `useNodeStyles.ts` 来自定义节点样式: + +```typescript +export function getNodeTypeConfig(type: string) { + const configs = { + start: { + label: '开始', + icon: 'play-circle', + color: '#10b981', + // 自定义样式 + }, + // 其他节点类型... + } + + return configs[type] || configs.default +} +``` + +### 边样式 + +边的样式在主组件中定义: + +```vue +:default-edge-options="{ + type: 'step', + style: { + stroke: '#6366f1', + strokeWidth: 2.5, + cursor: 'pointer', + filter: 'drop-shadow(0 2px 4px rgba(0,0,0,0.1))' + }, + markerEnd: { + type: MarkerType.ArrowClosed, + color: '#6366f1', + width: 16, + height: 16, + }, +}" +``` + +## 数据格式 + +### 节点数据格式 + +```typescript +interface Node { + id: string + type: string + position: { x: number, y: number } + data: { + customLabel: string + [key: string]: any + } +} +``` + +### 边数据格式 + +```typescript +interface Edge { + id: string + source: string + target: string + sourceHandle?: string + targetHandle?: string + type?: string +} +``` + +## 最佳实践 + +### 1. 性能优化 +- 大量节点时考虑虚拟化 +- 合理使用缓存机制 +- 避免频繁的状态更新 + +### 2. 用户体验 +- 提供清晰的操作反馈 +- 支持键盘快捷键 +- 保持操作的直观性 + +### 3. 数据管理 +- 定期保存到服务器 +- 提供数据导入导出功能 +- 支持版本控制机制 + +## 扩展开发 + +### 添加新节点类型 + +1. 在 `useNodeStyles.ts` 中添加新类型配置 +2. 在 `Toolbar.vue` 中添加新节点按钮 +3. 在 `CustomNode.vue` 中添加新节点渲染逻辑 + +### 添加新功能 + +1. 创建新的 composable 函数 +2. 在主组件中集成新功能 +3. 更新工具栏和用户界面 + +## 故障排除 + +### 常见问题 + +1. **节点无法拖拽** + - 检查拖拽事件处理 + - 确认节点类型配置正确 + +2. **撤销重做不工作** + - 检查历史记录状态 + - 确认状态保存时机 + +3. **数据丢失** + - 检查缓存配置 + - 确认 localStorage 可用 + +### 调试技巧 + +1. 使用 Vue DevTools 查看组件状态 +2. 检查浏览器控制台错误 +3. 验证数据格式正确性 + +## 更新日志 + +### v1.0.0 (2024-01-15) +- ✨ 初始版本发布 +- 🎯 基础流程图编辑功能 +- 🔧 拖拽创建节点 +- 🔗 节点连接功能 +- ↩️ 撤销重做支持 +- 💾 本地缓存功能 + +### v1.1.0 (2024-01-20) +- 🎨 新增多种节点类型 +- ⌨️ 键盘快捷键支持 +- 🖱️ 优化拖拽体验 +- 📱 响应式布局改进 + +### v1.2.0 (2024-01-25) +- 🔧 模块化重构 +- 📦 组合式函数优化 +- 🎯 性能提升 +- 🐛 修复已知问题 + +## 许可证 + +MIT License diff --git a/docs/图表.md b/docs/图表.md index 1de026e..a6c1077 100644 --- a/docs/图表.md +++ b/docs/图表.md @@ -1,41 +1,216 @@ -📊 可以添加的图表类型 -1. 提交效率趋势图 (折线图) -数据来源: durationData 中的 submission_count / problem_count -展示内容: 每个时间段的提交效率(提交次数/完成题目数),值越接近1说明一次AC率越高 -价值: 反映刷题质量的提升 -2. 排名分布图 (直方图/箱线图) -数据来源: solved 数组中每道题的 rank 和 ac_count -展示内容: 用户解题排名的分布情况(如:前10%、10-30%、30-50%等区间的题目数量) -价值: 了解解题速度和竞争力 -3. 等级分布饼图/环形图 -数据来源: solved 数组中每道题的 grade -展示内容: S/A/B/C 各等级题目的数量和占比 -价值: 直观看出题目质量分布 -4. 标签雷达图 -数据来源: tags 对象 -展示内容: 多维度展示各类标签的掌握程度(可以归一化处理) -价值: 可视化知识点覆盖面 -5. 时间活跃度分析 (热力矩阵) -数据来源: solved 数组中的 ac_time -展示内容: 按星期几和时间段统计做题分布(如:工作日vs周末,早中晚时段) -价值: 了解学习习惯和时间规律 -6. 难度-等级关联散点图 -数据来源: solved 数组中的难度信息和 grade -展示内容: X轴为难度,Y轴为等级,每个点代表一道题 -价值: 分析在不同难度下的表现 -7. 做题加速度图 -数据来源: durationData -展示内容: 每个时间段完成题目数的变化率 -价值: 看出学习动力的变化趋势 -8. 竞赛题目占比 -数据来源: solved 数组中的 contest_id 和 contest_count -展示内容: 竞赛题 vs 常规题的数量对比 -价值: 了解竞赛参与情况 -9. 连续做题天数统计 -数据来源: heatmapData -展示内容: 最长连续做题天数、当前连续天数等 -价值: 激励持续学习 -10. 月度对比雷达图 -数据来源: durationData -展示内容: 多个维度(完成题目数、提交次数、等级、效率等)的月度对比 -价值: 全面评估进步情况 \ No newline at end of file +# 图表组件说明 + +基于 Chart.js 和 Vue-ChartJS 构建的数据可视化组件库,为 OJ Next 项目提供丰富的图表展示功能。 + +## 技术栈 + +- **Chart.js** - 强大的图表库,支持多种图表类型 +- **Vue-ChartJS** - Chart.js 的 Vue 3 封装 +- **Vue 3 Composition API** - 现代化的组件开发方式 +- **TypeScript** - 完整的类型支持 + +## 现有图表组件 + +### 1. DurationChart 混合图表 +**文件位置**: `src/oj/ai/components/DurationChart.vue` + +**功能描述**: 展示用户学习进度的时间趋势,结合柱状图和折线图。 + +**数据来源**: `durationData` API 接口 +- 每周/每月的综合情况 +- 题目数、提交数、等级变化 + +**图表类型**: +- 柱状图:完成题目数 +- 折线图:提交次数、等级变化 + +**使用场景**: AI分析页面的主要图表 + +### 2. Heatmap 热力图 +**文件位置**: `src/oj/ai/components/Heatmap.vue` + +**功能描述**: 展示用户的提交活跃度分布。 + +**数据来源**: `heatmapData` API 接口 +- 按日期统计提交数 +- 可视化用户活跃度 + +**图表类型**: 热力图矩阵 + +**使用场景**: 展示学习习惯和时间规律 + +### 3. Details 详细数据 +**文件位置**: `src/oj/ai/components/Details.vue` + +**功能描述**: 展示用户详细的学习数据。 + +**数据来源**: `detailsData` API 接口 +- 用户等级、已解决题目列表 +- 标签统计、难度统计 +- 参赛次数等 + +**展示方式**: 数据表格和统计卡片 + +## 可扩展的图表类型 + +### 1. 提交效率趋势图 (折线图) +**数据来源**: `durationData` 中的 `submission_count / problem_count` +**展示内容**: 每个时间段的提交效率(提交次数/完成题目数) +**价值**: 反映刷题质量的提升,值越接近1说明一次AC率越高 + +### 2. 排名分布图 (直方图/箱线图) +**数据来源**: `solved` 数组中每道题的 `rank` 和 `ac_count` +**展示内容**: 用户解题排名的分布情况(如:前10%、10-30%、30-50%等区间的题目数量) +**价值**: 了解解题速度和竞争力 + +### 3. 等级分布饼图/环形图 +**数据来源**: `solved` 数组中每道题的 `grade` +**展示内容**: S/A/B/C 各等级题目的数量和占比 +**价值**: 直观看出题目质量分布 + +### 4. 标签雷达图 +**数据来源**: `tags` 对象 +**展示内容**: 多维度展示各类标签的掌握程度(可以归一化处理) +**价值**: 可视化知识点覆盖面 + +### 5. 时间活跃度分析 (热力矩阵) +**数据来源**: `solved` 数组中的 `ac_time` +**展示内容**: 按星期几和时间段统计做题分布(如:工作日vs周末,早中晚时段) +**价值**: 了解学习习惯和时间规律 + +### 6. 难度-等级关联散点图 +**数据来源**: `solved` 数组中的难度信息和 `grade` +**展示内容**: X轴为难度,Y轴为等级,每个点代表一道题 +**价值**: 分析在不同难度下的表现 + +### 7. 做题加速度图 +**数据来源**: `durationData` +**展示内容**: 每个时间段完成题目数的变化率 +**价值**: 看出学习动力的变化趋势 + +### 8. 竞赛题目占比 +**数据来源**: `solved` 数组中的 `contest_id` 和 `contest_count` +**展示内容**: 竞赛题 vs 常规题的数量对比 +**价值**: 了解竞赛参与情况 + +### 9. 连续做题天数统计 +**数据来源**: `heatmapData` +**展示内容**: 最长连续做题天数、当前连续天数等 +**价值**: 激励持续学习 + +### 10. 月度对比雷达图 +**数据来源**: `durationData` +**展示内容**: 多个维度(完成题目数、提交次数、等级、效率等)的月度对比 +**价值**: 全面评估进步情况 + +## 组件开发指南 + +### 创建新图表组件 + +```vue + + + +``` + +### 图表样式定制 + +```typescript +// 主题配置 +const theme = { + colors: { + primary: '#6366f1', + secondary: '#8b5cf6', + success: '#10b981', + warning: '#f59e0b', + error: '#ef4444' + }, + gradients: { + primary: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', + success: 'linear-gradient(135deg, #11998e 0%, #38ef7d 100%)' + } +} +``` + +## 性能优化 + +### 1. 数据懒加载 +- 按需加载图表数据 +- 使用虚拟滚动处理大量数据 + +### 2. 图表缓存 +- 缓存计算结果 +- 避免重复渲染 + +### 3. 响应式设计 +- 自适应容器大小 +- 移动端优化 + +## 最佳实践 + +### 1. 数据预处理 +- 在组件外部处理数据 +- 使用 computed 属性缓存计算结果 + +### 2. 错误处理 +- 添加数据验证 +- 提供降级方案 + +### 3. 用户体验 +- 添加加载状态 +- 提供交互反馈 + +## 更新日志 + +### v1.0.0 (2024-01-15) +- ✨ 初始版本发布 +- 📊 基础图表组件 +- 🎨 主题样式支持 +- 📱 响应式设计 + +### v1.1.0 (2024-01-20) +- 🔧 性能优化 +- 📈 新增混合图表 +- 🎯 交互体验改进 + +## 许可证 + +MIT License \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7aaf0c1..54edc2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,12 @@ "dependencies": { "@codemirror/lang-cpp": "^6.0.3", "@codemirror/lang-python": "^6.2.1", + "@vue-flow/background": "^1.3.2", + "@vue-flow/controls": "^1.1.3", + "@vue-flow/core": "^1.47.0", + "@vue-flow/minimap": "^1.5.4", + "@vue-flow/node-resizer": "^1.5.0", + "@vue-flow/node-toolbar": "^1.1.1", "@vueuse/core": "^13.9.0", "@vueuse/router": "^13.9.0", "@wangeditor-next/editor": "^5.6.46", @@ -1722,6 +1728,175 @@ "integrity": "sha512-YIfAvArSFVXmWvoF+DEGD0FhkhVNcCtVWWkfYtj76eSrwHh/wuEEFhiEubg1XLNM3tChO8FH8xJCT/hnizjgFQ==", "license": "MIT" }, + "node_modules/@vue-flow/background": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@vue-flow/background/-/background-1.3.2.tgz", + "integrity": "sha512-eJPhDcLj1wEo45bBoqTXw1uhl0yK2RaQGnEINqvvBsAFKh/camHJd5NPmOdS1w+M9lggc9igUewxaEd3iCQX2w==", + "license": "MIT", + "peerDependencies": { + "@vue-flow/core": "^1.23.0", + "vue": "^3.3.0" + } + }, + "node_modules/@vue-flow/controls": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@vue-flow/controls/-/controls-1.1.3.tgz", + "integrity": "sha512-XCf+G+jCvaWURdFlZmOjifZGw3XMhN5hHlfMGkWh9xot+9nH9gdTZtn+ldIJKtarg3B21iyHU8JjKDhYcB6JMw==", + "license": "MIT", + "peerDependencies": { + "@vue-flow/core": "^1.23.0", + "vue": "^3.3.0" + } + }, + "node_modules/@vue-flow/core": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/@vue-flow/core/-/core-1.47.0.tgz", + "integrity": "sha512-w+qrm/xjQP5NUeKUOMIbQvpOeivTbGZtY2lGffK5kHiN3ZLyEazhESc8OeIV9NZkK2T5DIeyX/nhHxCC45HLiw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vueuse/core": "^10.5.0", + "d3-drag": "^3.0.0", + "d3-interpolate": "^3.0.1", + "d3-selection": "^3.0.0", + "d3-zoom": "^3.0.0" + }, + "peerDependencies": { + "vue": "^3.3.0" + } + }, + "node_modules/@vue-flow/core/node_modules/@types/web-bluetooth": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", + "license": "MIT" + }, + "node_modules/@vue-flow/core/node_modules/@vueuse/core": { + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.1.tgz", + "integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "10.11.1", + "@vueuse/shared": "10.11.1", + "vue-demi": ">=0.14.8" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vue-flow/core/node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vue-flow/core/node_modules/@vueuse/metadata": { + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.1.tgz", + "integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vue-flow/core/node_modules/@vueuse/shared": { + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.1.tgz", + "integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==", + "license": "MIT", + "dependencies": { + "vue-demi": ">=0.14.8" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vue-flow/core/node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vue-flow/minimap": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@vue-flow/minimap/-/minimap-1.5.4.tgz", + "integrity": "sha512-l4C+XTAXnRxsRpUdN7cAVFBennC1sVRzq4bDSpVK+ag7tdMczAnhFYGgbLkUw3v3sY6gokyWwMl8CDonp8eB2g==", + "license": "MIT", + "dependencies": { + "d3-selection": "^3.0.0", + "d3-zoom": "^3.0.0" + }, + "peerDependencies": { + "@vue-flow/core": "^1.23.0", + "vue": "^3.3.0" + } + }, + "node_modules/@vue-flow/node-resizer": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue-flow/node-resizer/-/node-resizer-1.5.0.tgz", + "integrity": "sha512-FmvOZ6+yVrBEf+8oJcCU20PUZ105QsyM01iiP4vTKHGJ01hzoh9d0/wP9iJkxkIpvBU59CyOHyTKQZlDr4qDhA==", + "license": "MIT", + "dependencies": { + "d3-drag": "^3.0.0", + "d3-selection": "^3.0.0" + }, + "peerDependencies": { + "@vue-flow/core": "^1.23.0", + "vue": "^3.3.0" + } + }, + "node_modules/@vue-flow/node-toolbar": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@vue-flow/node-toolbar/-/node-toolbar-1.1.1.tgz", + "integrity": "sha512-vgSnGMLd3FXstdpvC721qcBDzGkPsudmyA8urEP55/EMikCp59klgzPvVULTDxxsew5MdXtTBCumsqOi+PXJdg==", + "license": "MIT", + "peerDependencies": { + "@vue-flow/core": "^1.23.0", + "vue": "^3.3.0" + } + }, "node_modules/@vue/compiler-core": { "version": "3.5.22", "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.22.tgz", diff --git a/package.json b/package.json index 96be0aa..0f89d69 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,12 @@ "dependencies": { "@codemirror/lang-cpp": "^6.0.3", "@codemirror/lang-python": "^6.2.1", + "@vue-flow/background": "^1.3.2", + "@vue-flow/controls": "^1.1.3", + "@vue-flow/core": "^1.47.0", + "@vue-flow/minimap": "^1.5.4", + "@vue-flow/node-resizer": "^1.5.0", + "@vue-flow/node-toolbar": "^1.1.1", "@vueuse/core": "^13.9.0", "@vueuse/router": "^13.9.0", "@wangeditor-next/editor": "^5.6.46", diff --git a/src/oj/problem/components/ProblemEditor.vue b/src/oj/problem/components/ProblemEditor.vue index 4c9a60a..58ccc47 100644 --- a/src/oj/problem/components/ProblemEditor.vue +++ b/src/oj/problem/components/ProblemEditor.vue @@ -16,6 +16,7 @@ const FlowchartEditor = defineAsyncComponent( const route = useRoute() const formRef = useTemplateRef>("formRef") +const flowchartEditorRef = useTemplateRef("flowchartEditorRef") const codeStore = useCodeStore() const problemStore = useProblemStore() @@ -78,6 +79,9 @@ const handleSyncStatusChange = (status: { }) => { syncStatus.setOtherUser(status.otherUser) } + +// 提供FlowchartEditor的ref给子组件 +provide('flowchartEditorRef', flowchartEditorRef)