From ae1fb329b5522dbecd21379a7ef23c8959d98de7 Mon Sep 17 00:00:00 2001
From: yuetsh <517252939@qq.com>
Date: Thu, 6 Aug 2026 21:18:16 -0600
Subject: [PATCH] =?UTF-8?q?feat(=E9=98=B6=E6=AE=B51):=20=E6=90=AC=E5=85=A5?=
=?UTF-8?q?=20ojnext=20=E4=B8=BA=20apps/web=EF=BC=8C=E6=9C=AA=E6=94=B9?=
=?UTF-8?q?=E4=B8=9A=E5=8A=A1=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 3 +
apps/web/.browserslistrc | 1 +
apps/web/.env.production | 8 +
apps/web/.env.staging | 8 +
apps/web/.env.test | 8 +
apps/web/.github/workflows/deploy.yml | 46 +
apps/web/.gitignore | 30 +
apps/web/.prettierrc.toml | 1 +
apps/web/CLAUDE.md | 114 ++
apps/web/README.md | 1 +
apps/web/docs/API接口对比分析.md | 548 ++++++
apps/web/docs/FlowchartEditor.md | 311 ++++
...26-06-14-submit-formatting-button-state.md | 259 +++
.../plans/2026-07-26-demo-student-view.md | 296 ++++
...4-submit-formatting-button-state-design.md | 34 +
...2026-07-05-sql-min-two-testcases-design.md | 28 +
...-07-05-sql-schema-autocompletion-design.md | 50 +
.../2026-07-26-demo-student-view-design.md | 102 ++
apps/web/docs/图表.md | 216 +++
apps/web/index.html | 17 +
apps/web/package.json | 67 +
apps/web/public/A.png | Bin 0 -> 8228 bytes
apps/web/public/B.png | Bin 0 -> 9034 bytes
apps/web/public/C.png | Bin 0 -> 7776 bytes
apps/web/public/Monaco.ttf | Bin 0 -> 48116 bytes
apps/web/public/S.png | Bin 0 -> 11789 bytes
apps/web/public/badge-1.png | Bin 0 -> 2214 bytes
apps/web/public/badge-2.png | Bin 0 -> 2250 bytes
apps/web/public/badge-3.png | Bin 0 -> 2894 bytes
apps/web/public/badge-4.png | Bin 0 -> 2749 bytes
apps/web/public/badge-5.png | Bin 0 -> 3318 bytes
apps/web/public/badge-6.png | Bin 0 -> 3194 bytes
apps/web/public/favicon.ico | Bin 0 -> 2393 bytes
apps/web/public/noto--dog-face.ico | Bin 0 -> 192545 bytes
apps/web/public/style.css | 20 +
apps/web/src/App.vue | 77 +
.../components/AchievementModal.vue | 185 +++
apps/web/src/admin/achievement/list.vue | 144 ++
apps/web/src/admin/ai/list.vue | 206 +++
.../admin/announcement/components/Actions.vue | 39 +
apps/web/src/admin/announcement/detail.vue | 117 ++
apps/web/src/admin/announcement/list.vue | 113 ++
apps/web/src/admin/api.ts | 600 +++++++
apps/web/src/admin/communication/messages.vue | 2 +
.../src/admin/contest/components/Actions.vue | 68 +
apps/web/src/admin/contest/detail.vue | 196 +++
apps/web/src/admin/contest/helper.vue | 326 ++++
apps/web/src/admin/contest/list.vue | 132 ++
apps/web/src/admin/problem/Stuck.vue | 56 +
apps/web/src/admin/problem/TopACTrend.vue | 202 +++
.../src/admin/problem/components/Actions.vue | 160 ++
.../admin/problem/components/AddButton.vue | 47 +
.../problem/components/AstRulesEditor.vue | 397 +++++
.../problem/components/BatchTagModal.vue | 109 ++
.../src/admin/problem/components/Modal.vue | 94 ++
.../problem/components/SQLTestcaseEditor.vue | 345 ++++
.../problem/components/TagProblemsModal.vue | 147 ++
.../problem/components/TestcaseGenerator.vue | 263 +++
apps/web/src/admin/problem/detail.vue | 920 ++++++++++
apps/web/src/admin/problem/list.vue | 335 ++++
apps/web/src/admin/problem/tags.vue | 186 +++
.../admin/problemset/components/Actions.vue | 105 ++
.../problemset/components/AddBadgeModal.vue | 162 ++
.../problemset/components/AddProblemModal.vue | 103 ++
.../problemset/components/BadgeManagement.vue | 96 ++
.../problemset/components/EditBadgeModal.vue | 167 ++
.../components/EditProblemModal.vue | 100 ++
.../components/ProblemManagement.vue | 73 +
.../problemset/components/ProblemSetInfo.vue | 70 +
.../components/ProgressManagement.vue | 69 +
apps/web/src/admin/problemset/detail.vue | 270 +++
apps/web/src/admin/problemset/edit.vue | 169 ++
apps/web/src/admin/problemset/list.vue | 212 +++
apps/web/src/admin/setting/config.vue | 314 ++++
apps/web/src/admin/setting/home.vue | 244 +++
apps/web/src/admin/transforms.ts | 20 +
.../src/admin/tutorial/components/Actions.vue | 43 +
.../tutorial/components/ExerciseManager.vue | 652 ++++++++
apps/web/src/admin/tutorial/detail.vue | 133 ++
apps/web/src/admin/tutorial/list.vue | 107 ++
.../web/src/admin/user/components/Actions.vue | 55 +
apps/web/src/admin/user/components/Name.vue | 42 +
apps/web/src/admin/user/generate.vue | 107 ++
apps/web/src/admin/user/list.vue | 359 ++++
apps/web/src/env.d.ts | 16 +
apps/web/src/index.css | 29 +
apps/web/src/main.ts | 92 +
apps/web/src/mermaid-legacy.d.ts | 1 +
apps/web/src/oj/achievement/api.ts | 27 +
.../components/AchievementCard.vue | 134 ++
apps/web/src/oj/achievement/index.vue | 227 +++
apps/web/src/oj/ai/analysis.vue | 122 ++
apps/web/src/oj/ai/components/AI.vue | 91 +
.../oj/ai/components/DifficultyGradeChart.vue | 144 ++
.../src/oj/ai/components/DurationChart.vue | 204 +++
.../src/oj/ai/components/EfficiencyChart.vue | 234 +++
apps/web/src/oj/ai/components/Grade.vue | 53 +
apps/web/src/oj/ai/components/Heatmap.vue | 251 +++
apps/web/src/oj/ai/components/Overview.vue | 63 +
.../src/oj/ai/components/ProgressChart.vue | 271 +++
.../ai/components/RankDistributionChart.vue | 132 ++
apps/web/src/oj/ai/components/SolvedTable.vue | 154 ++
apps/web/src/oj/ai/components/StreakStats.vue | 177 ++
apps/web/src/oj/ai/components/TagTitle.vue | 21 +
.../src/oj/ai/components/TagsRadarChart.vue | 154 ++
.../oj/ai/components/TimeActivityHeatmap.vue | 154 ++
.../announcement/components/TitleWithTag.vue | 14 +
apps/web/src/oj/announcement/list.vue | 94 ++
apps/web/src/oj/api.ts | 435 +++++
apps/web/src/oj/class/pk.vue | 1260 ++++++++++++++
apps/web/src/oj/composables/syncStatus.ts | 73 +
.../oj/contest/components/AcAndSubmission.vue | 25 +
.../src/oj/contest/components/ContestInfo.vue | 42 +
.../src/oj/contest/components/ContestMenu.vue | 56 +
.../src/oj/contest/components/LineChart.vue | 231 +++
apps/web/src/oj/contest/detail.vue | 93 ++
apps/web/src/oj/contest/list.vue | 180 ++
apps/web/src/oj/contest/pages/problems.vue | 61 +
apps/web/src/oj/contest/pages/rank.vue | 341 ++++
apps/web/src/oj/flowchart/index.vue | 7 +
.../src/oj/learn/components/ExerciseDebug.vue | 121 ++
.../src/oj/learn/components/ExerciseFill.vue | 135 ++
.../src/oj/learn/components/ExerciseGroup.vue | 183 ++
.../src/oj/learn/components/ExerciseMatch.vue | 184 ++
.../src/oj/learn/components/ExerciseMcq.vue | 123 ++
.../oj/learn/components/ExercisePredict.vue | 92 +
.../src/oj/learn/components/ExerciseSort.vue | 130 ++
.../oj/learn/components/ExerciseWidget.vue | 41 +
.../learn/components/exercise-highlight.css | 50 +
.../oj/learn/composables/useCodeHighlight.ts | 41 +
.../oj/learn/composables/useExerciseParse.ts | 36 +
.../src/oj/learn/composables/useShuffle.ts | 9 +
apps/web/src/oj/learn/index.vue | 255 +++
.../oj/problem/components/ContestEditor.vue | 69 +
.../oj/problem/components/EditorForTest.vue | 161 ++
apps/web/src/oj/problem/components/Form.vue | 291 ++++
.../oj/problem/components/MyFlowchartTab.vue | 42 +
.../oj/problem/components/ProblemContent.vue | 550 ++++++
.../oj/problem/components/ProblemEditor.vue | 123 ++
.../problem/components/ProblemFlowchart.vue | 43 +
.../src/oj/problem/components/ProblemInfo.vue | 177 ++
.../problem/components/ProblemListTitle.vue | 28 +
.../oj/problem/components/ProblemReaction.vue | 698 ++++++++
.../oj/problem/components/ProblemStatus.vue | 24 +
.../problem/components/ProblemSubmission.vue | 343 ++++
.../problem/components/ProblemYearlyChart.vue | 85 +
.../oj/problem/components/SQLDataTable.vue | 60 +
.../problem/components/SubmissionResult.vue | 237 +++
.../src/oj/problem/components/SubmitCode.vue | 275 +++
.../oj/problem/components/SubmitFlowchart.vue | 422 +++++
.../problem/components/submitButtonState.ts | 53 +
.../oj/problem/composables/useFireworks.ts | 391 +++++
.../composables/useMermaidConverter.ts | 125 ++
.../composables/useSubmissionMonitor.ts | 190 +++
apps/web/src/oj/problem/detail.vue | 284 ++++
apps/web/src/oj/problem/list.vue | 342 ++++
.../src/oj/problem/utils/pythonSyntaxCheck.ts | 53 +
.../components/ProblemSetHeader.vue | 109 ++
.../components/ProblemSetProblemsList.vue | 81 +
.../components/UserProgressView.vue | 268 +++
apps/web/src/oj/problemset/detail.vue | 139 ++
apps/web/src/oj/problemset/list.vue | 274 +++
apps/web/src/oj/rank/components/Chart.vue | 114 ++
apps/web/src/oj/rank/components/Index.vue | 31 +
apps/web/src/oj/rank/list.vue | 880 ++++++++++
apps/web/src/oj/store/ai.ts | 206 +++
apps/web/src/oj/store/code.ts | 94 ++
apps/web/src/oj/store/contest.ts | 116 ++
apps/web/src/oj/store/problem.ts | 34 +
.../components/ButtonWithSearch.vue | 53 +
.../submission/components/FlowchartLink.vue | 35 +
.../components/FlowchartScoreDetail.vue | 226 +++
.../src/oj/submission/components/Grade.vue | 25 +
.../submission/components/SubmissionLink.vue | 52 +
apps/web/src/oj/submission/detail.vue | 168 ++
apps/web/src/oj/submission/list.vue | 573 +++++++
apps/web/src/oj/transforms.ts | 29 +
apps/web/src/oj/user/index.vue | 331 ++++
apps/web/src/oj/user/message.vue | 71 +
apps/web/src/oj/user/setting.vue | 76 +
apps/web/src/routes.ts | 339 ++++
apps/web/src/shared/api.ts | 34 +
.../src/shared/components/AchievementIcon.vue | 50 +
.../shared/components/AchievementToast.vue | 101 ++
.../src/shared/components/AuthorSelect.vue | 35 +
apps/web/src/shared/components/Beian.vue | 69 +
apps/web/src/shared/components/CodeEditor.vue | 65 +
.../src/shared/components/ContestTitle.vue | 18 +
.../web/src/shared/components/ContestType.vue | 21 +
apps/web/src/shared/components/Copy.vue | 35 +
.../components/FlowchartEditor/CustomNode.vue | 275 +++
.../FlowchartEditor/NodeActions.vue | 60 +
.../FlowchartEditor/NodeHandles.vue | 238 +++
.../components/FlowchartEditor/Toolbar.vue | 413 +++++
.../components/FlowchartEditor/index.vue | 325 ++++
.../components/FlowchartEditor/useCache.ts | 89 +
.../components/FlowchartEditor/useDnD.ts | 84 +
.../FlowchartEditor/useFlowOperations.ts | 142 ++
.../components/FlowchartEditor/useHistory.ts | 72 +
.../FlowchartEditor/useNodeStyles.ts | 137 ++
.../components/FlowchartStatisticsPanel.vue | 577 +++++++
apps/web/src/shared/components/Header.vue | 356 ++++
apps/web/src/shared/components/Hitokoto.vue | 69 +
apps/web/src/shared/components/IconButton.vue | 29 +
apps/web/src/shared/components/Login.vue | 201 +++
.../shared/components/LoginSummaryModal.vue | 83 +
.../src/shared/components/MarkdownEditor.vue | 40 +
.../src/shared/components/MermaidEditor.vue | 93 ++
apps/web/src/shared/components/Pagination.vue | 61 +
apps/web/src/shared/components/Signup.vue | 131 ++
.../src/shared/components/StatisticsPanel.vue | 470 ++++++
.../shared/components/SubmissionResultTag.vue | 17 +
.../src/shared/components/SyncCodeEditor.vue | 153 ++
apps/web/src/shared/components/TextCopy.vue | 33 +
apps/web/src/shared/components/TextEditor.vue | 144 ++
apps/web/src/shared/components/UserBadge.vue | 87 +
.../web/src/shared/composables/breakpoints.ts | 20 +
.../src/shared/composables/configUpdate.ts | 41 +
.../src/shared/composables/learnProgress.ts | 15 +
apps/web/src/shared/composables/maxkb.ts | 132 ++
apps/web/src/shared/composables/pagination.ts | 154 ++
apps/web/src/shared/composables/rarity.ts | 15 +
apps/web/src/shared/composables/sync.ts | 412 +++++
apps/web/src/shared/composables/useMermaid.ts | 334 ++++
apps/web/src/shared/composables/websocket.ts | 544 ++++++
.../src/shared/extensions/autocompletion.ts | 107 ++
apps/web/src/shared/extensions/baseTheme.ts | 9 +
apps/web/src/shared/extensions/c.ts | 257 +++
apps/web/src/shared/extensions/python.ts | 608 +++++++
apps/web/src/shared/extensions/sql.ts | 404 +++++
apps/web/src/shared/layout/admin.vue | 204 +++
apps/web/src/shared/layout/default.vue | 50 +
apps/web/src/shared/store/achievement.ts | 64 +
apps/web/src/shared/store/authModal.ts | 155 ++
apps/web/src/shared/store/config.ts | 24 +
apps/web/src/shared/store/loginSummary.ts | 74 +
apps/web/src/shared/store/myFlowchart.ts | 18 +
apps/web/src/shared/store/screenMode.ts | 34 +
apps/web/src/shared/store/user.ts | 94 ++
apps/web/src/shared/themes/createTheme.ts | 110 ++
apps/web/src/shared/themes/oneDark.ts | 149 ++
apps/web/src/shared/themes/smoothy.ts | 100 ++
apps/web/src/utils/constants.ts | 370 +++++
apps/web/src/utils/download.ts | 23 +
apps/web/src/utils/functions.ts | 600 +++++++
apps/web/src/utils/http.ts | 79 +
apps/web/src/utils/judge.ts | 37 +
apps/web/src/utils/permissions.ts | 108 ++
apps/web/src/utils/renders.ts | 9 +
apps/web/src/utils/storage.ts | 21 +
apps/web/src/utils/stream.ts | 94 ++
apps/web/src/utils/types.ts | 790 +++++++++
apps/web/tests/submitButtonState.test.ts | 51 +
apps/web/tsconfig.app.json | 23 +
apps/web/tsconfig.json | 7 +
apps/web/tsconfig.node.json | 24 +
apps/web/vite.config.ts | 175 ++
bun.lock | 1476 ++++++++++++++++-
258 files changed, 40490 insertions(+), 91 deletions(-)
create mode 100644 apps/web/.browserslistrc
create mode 100644 apps/web/.env.production
create mode 100644 apps/web/.env.staging
create mode 100644 apps/web/.env.test
create mode 100644 apps/web/.github/workflows/deploy.yml
create mode 100644 apps/web/.gitignore
create mode 100644 apps/web/.prettierrc.toml
create mode 100644 apps/web/CLAUDE.md
create mode 100644 apps/web/README.md
create mode 100644 apps/web/docs/API接口对比分析.md
create mode 100644 apps/web/docs/FlowchartEditor.md
create mode 100644 apps/web/docs/superpowers/plans/2026-06-14-submit-formatting-button-state.md
create mode 100644 apps/web/docs/superpowers/plans/2026-07-26-demo-student-view.md
create mode 100644 apps/web/docs/superpowers/specs/2026-06-14-submit-formatting-button-state-design.md
create mode 100644 apps/web/docs/superpowers/specs/2026-07-05-sql-min-two-testcases-design.md
create mode 100644 apps/web/docs/superpowers/specs/2026-07-05-sql-schema-autocompletion-design.md
create mode 100644 apps/web/docs/superpowers/specs/2026-07-26-demo-student-view-design.md
create mode 100644 apps/web/docs/图表.md
create mode 100644 apps/web/index.html
create mode 100644 apps/web/package.json
create mode 100644 apps/web/public/A.png
create mode 100644 apps/web/public/B.png
create mode 100644 apps/web/public/C.png
create mode 100644 apps/web/public/Monaco.ttf
create mode 100644 apps/web/public/S.png
create mode 100644 apps/web/public/badge-1.png
create mode 100644 apps/web/public/badge-2.png
create mode 100644 apps/web/public/badge-3.png
create mode 100644 apps/web/public/badge-4.png
create mode 100644 apps/web/public/badge-5.png
create mode 100644 apps/web/public/badge-6.png
create mode 100644 apps/web/public/favicon.ico
create mode 100644 apps/web/public/noto--dog-face.ico
create mode 100644 apps/web/public/style.css
create mode 100644 apps/web/src/App.vue
create mode 100644 apps/web/src/admin/achievement/components/AchievementModal.vue
create mode 100644 apps/web/src/admin/achievement/list.vue
create mode 100644 apps/web/src/admin/ai/list.vue
create mode 100644 apps/web/src/admin/announcement/components/Actions.vue
create mode 100644 apps/web/src/admin/announcement/detail.vue
create mode 100644 apps/web/src/admin/announcement/list.vue
create mode 100644 apps/web/src/admin/api.ts
create mode 100644 apps/web/src/admin/communication/messages.vue
create mode 100644 apps/web/src/admin/contest/components/Actions.vue
create mode 100644 apps/web/src/admin/contest/detail.vue
create mode 100644 apps/web/src/admin/contest/helper.vue
create mode 100644 apps/web/src/admin/contest/list.vue
create mode 100644 apps/web/src/admin/problem/Stuck.vue
create mode 100644 apps/web/src/admin/problem/TopACTrend.vue
create mode 100644 apps/web/src/admin/problem/components/Actions.vue
create mode 100644 apps/web/src/admin/problem/components/AddButton.vue
create mode 100644 apps/web/src/admin/problem/components/AstRulesEditor.vue
create mode 100644 apps/web/src/admin/problem/components/BatchTagModal.vue
create mode 100644 apps/web/src/admin/problem/components/Modal.vue
create mode 100644 apps/web/src/admin/problem/components/SQLTestcaseEditor.vue
create mode 100644 apps/web/src/admin/problem/components/TagProblemsModal.vue
create mode 100644 apps/web/src/admin/problem/components/TestcaseGenerator.vue
create mode 100644 apps/web/src/admin/problem/detail.vue
create mode 100644 apps/web/src/admin/problem/list.vue
create mode 100644 apps/web/src/admin/problem/tags.vue
create mode 100644 apps/web/src/admin/problemset/components/Actions.vue
create mode 100644 apps/web/src/admin/problemset/components/AddBadgeModal.vue
create mode 100644 apps/web/src/admin/problemset/components/AddProblemModal.vue
create mode 100644 apps/web/src/admin/problemset/components/BadgeManagement.vue
create mode 100644 apps/web/src/admin/problemset/components/EditBadgeModal.vue
create mode 100644 apps/web/src/admin/problemset/components/EditProblemModal.vue
create mode 100644 apps/web/src/admin/problemset/components/ProblemManagement.vue
create mode 100644 apps/web/src/admin/problemset/components/ProblemSetInfo.vue
create mode 100644 apps/web/src/admin/problemset/components/ProgressManagement.vue
create mode 100644 apps/web/src/admin/problemset/detail.vue
create mode 100644 apps/web/src/admin/problemset/edit.vue
create mode 100644 apps/web/src/admin/problemset/list.vue
create mode 100644 apps/web/src/admin/setting/config.vue
create mode 100644 apps/web/src/admin/setting/home.vue
create mode 100644 apps/web/src/admin/transforms.ts
create mode 100644 apps/web/src/admin/tutorial/components/Actions.vue
create mode 100644 apps/web/src/admin/tutorial/components/ExerciseManager.vue
create mode 100644 apps/web/src/admin/tutorial/detail.vue
create mode 100644 apps/web/src/admin/tutorial/list.vue
create mode 100644 apps/web/src/admin/user/components/Actions.vue
create mode 100644 apps/web/src/admin/user/components/Name.vue
create mode 100644 apps/web/src/admin/user/generate.vue
create mode 100644 apps/web/src/admin/user/list.vue
create mode 100644 apps/web/src/env.d.ts
create mode 100644 apps/web/src/index.css
create mode 100644 apps/web/src/main.ts
create mode 100644 apps/web/src/mermaid-legacy.d.ts
create mode 100644 apps/web/src/oj/achievement/api.ts
create mode 100644 apps/web/src/oj/achievement/components/AchievementCard.vue
create mode 100644 apps/web/src/oj/achievement/index.vue
create mode 100644 apps/web/src/oj/ai/analysis.vue
create mode 100644 apps/web/src/oj/ai/components/AI.vue
create mode 100644 apps/web/src/oj/ai/components/DifficultyGradeChart.vue
create mode 100644 apps/web/src/oj/ai/components/DurationChart.vue
create mode 100644 apps/web/src/oj/ai/components/EfficiencyChart.vue
create mode 100644 apps/web/src/oj/ai/components/Grade.vue
create mode 100644 apps/web/src/oj/ai/components/Heatmap.vue
create mode 100644 apps/web/src/oj/ai/components/Overview.vue
create mode 100644 apps/web/src/oj/ai/components/ProgressChart.vue
create mode 100644 apps/web/src/oj/ai/components/RankDistributionChart.vue
create mode 100644 apps/web/src/oj/ai/components/SolvedTable.vue
create mode 100644 apps/web/src/oj/ai/components/StreakStats.vue
create mode 100644 apps/web/src/oj/ai/components/TagTitle.vue
create mode 100644 apps/web/src/oj/ai/components/TagsRadarChart.vue
create mode 100644 apps/web/src/oj/ai/components/TimeActivityHeatmap.vue
create mode 100644 apps/web/src/oj/announcement/components/TitleWithTag.vue
create mode 100644 apps/web/src/oj/announcement/list.vue
create mode 100644 apps/web/src/oj/api.ts
create mode 100644 apps/web/src/oj/class/pk.vue
create mode 100644 apps/web/src/oj/composables/syncStatus.ts
create mode 100644 apps/web/src/oj/contest/components/AcAndSubmission.vue
create mode 100644 apps/web/src/oj/contest/components/ContestInfo.vue
create mode 100644 apps/web/src/oj/contest/components/ContestMenu.vue
create mode 100644 apps/web/src/oj/contest/components/LineChart.vue
create mode 100644 apps/web/src/oj/contest/detail.vue
create mode 100644 apps/web/src/oj/contest/list.vue
create mode 100644 apps/web/src/oj/contest/pages/problems.vue
create mode 100644 apps/web/src/oj/contest/pages/rank.vue
create mode 100644 apps/web/src/oj/flowchart/index.vue
create mode 100644 apps/web/src/oj/learn/components/ExerciseDebug.vue
create mode 100644 apps/web/src/oj/learn/components/ExerciseFill.vue
create mode 100644 apps/web/src/oj/learn/components/ExerciseGroup.vue
create mode 100644 apps/web/src/oj/learn/components/ExerciseMatch.vue
create mode 100644 apps/web/src/oj/learn/components/ExerciseMcq.vue
create mode 100644 apps/web/src/oj/learn/components/ExercisePredict.vue
create mode 100644 apps/web/src/oj/learn/components/ExerciseSort.vue
create mode 100644 apps/web/src/oj/learn/components/ExerciseWidget.vue
create mode 100644 apps/web/src/oj/learn/components/exercise-highlight.css
create mode 100644 apps/web/src/oj/learn/composables/useCodeHighlight.ts
create mode 100644 apps/web/src/oj/learn/composables/useExerciseParse.ts
create mode 100644 apps/web/src/oj/learn/composables/useShuffle.ts
create mode 100644 apps/web/src/oj/learn/index.vue
create mode 100644 apps/web/src/oj/problem/components/ContestEditor.vue
create mode 100644 apps/web/src/oj/problem/components/EditorForTest.vue
create mode 100644 apps/web/src/oj/problem/components/Form.vue
create mode 100644 apps/web/src/oj/problem/components/MyFlowchartTab.vue
create mode 100644 apps/web/src/oj/problem/components/ProblemContent.vue
create mode 100644 apps/web/src/oj/problem/components/ProblemEditor.vue
create mode 100644 apps/web/src/oj/problem/components/ProblemFlowchart.vue
create mode 100644 apps/web/src/oj/problem/components/ProblemInfo.vue
create mode 100644 apps/web/src/oj/problem/components/ProblemListTitle.vue
create mode 100644 apps/web/src/oj/problem/components/ProblemReaction.vue
create mode 100644 apps/web/src/oj/problem/components/ProblemStatus.vue
create mode 100644 apps/web/src/oj/problem/components/ProblemSubmission.vue
create mode 100644 apps/web/src/oj/problem/components/ProblemYearlyChart.vue
create mode 100644 apps/web/src/oj/problem/components/SQLDataTable.vue
create mode 100644 apps/web/src/oj/problem/components/SubmissionResult.vue
create mode 100644 apps/web/src/oj/problem/components/SubmitCode.vue
create mode 100644 apps/web/src/oj/problem/components/SubmitFlowchart.vue
create mode 100644 apps/web/src/oj/problem/components/submitButtonState.ts
create mode 100644 apps/web/src/oj/problem/composables/useFireworks.ts
create mode 100644 apps/web/src/oj/problem/composables/useMermaidConverter.ts
create mode 100644 apps/web/src/oj/problem/composables/useSubmissionMonitor.ts
create mode 100644 apps/web/src/oj/problem/detail.vue
create mode 100644 apps/web/src/oj/problem/list.vue
create mode 100644 apps/web/src/oj/problem/utils/pythonSyntaxCheck.ts
create mode 100644 apps/web/src/oj/problemset/components/ProblemSetHeader.vue
create mode 100644 apps/web/src/oj/problemset/components/ProblemSetProblemsList.vue
create mode 100644 apps/web/src/oj/problemset/components/UserProgressView.vue
create mode 100644 apps/web/src/oj/problemset/detail.vue
create mode 100644 apps/web/src/oj/problemset/list.vue
create mode 100644 apps/web/src/oj/rank/components/Chart.vue
create mode 100644 apps/web/src/oj/rank/components/Index.vue
create mode 100644 apps/web/src/oj/rank/list.vue
create mode 100644 apps/web/src/oj/store/ai.ts
create mode 100644 apps/web/src/oj/store/code.ts
create mode 100644 apps/web/src/oj/store/contest.ts
create mode 100644 apps/web/src/oj/store/problem.ts
create mode 100644 apps/web/src/oj/submission/components/ButtonWithSearch.vue
create mode 100644 apps/web/src/oj/submission/components/FlowchartLink.vue
create mode 100644 apps/web/src/oj/submission/components/FlowchartScoreDetail.vue
create mode 100644 apps/web/src/oj/submission/components/Grade.vue
create mode 100644 apps/web/src/oj/submission/components/SubmissionLink.vue
create mode 100644 apps/web/src/oj/submission/detail.vue
create mode 100644 apps/web/src/oj/submission/list.vue
create mode 100644 apps/web/src/oj/transforms.ts
create mode 100644 apps/web/src/oj/user/index.vue
create mode 100644 apps/web/src/oj/user/message.vue
create mode 100644 apps/web/src/oj/user/setting.vue
create mode 100644 apps/web/src/routes.ts
create mode 100644 apps/web/src/shared/api.ts
create mode 100644 apps/web/src/shared/components/AchievementIcon.vue
create mode 100644 apps/web/src/shared/components/AchievementToast.vue
create mode 100644 apps/web/src/shared/components/AuthorSelect.vue
create mode 100644 apps/web/src/shared/components/Beian.vue
create mode 100644 apps/web/src/shared/components/CodeEditor.vue
create mode 100644 apps/web/src/shared/components/ContestTitle.vue
create mode 100644 apps/web/src/shared/components/ContestType.vue
create mode 100644 apps/web/src/shared/components/Copy.vue
create mode 100644 apps/web/src/shared/components/FlowchartEditor/CustomNode.vue
create mode 100644 apps/web/src/shared/components/FlowchartEditor/NodeActions.vue
create mode 100644 apps/web/src/shared/components/FlowchartEditor/NodeHandles.vue
create mode 100644 apps/web/src/shared/components/FlowchartEditor/Toolbar.vue
create mode 100644 apps/web/src/shared/components/FlowchartEditor/index.vue
create mode 100644 apps/web/src/shared/components/FlowchartEditor/useCache.ts
create mode 100644 apps/web/src/shared/components/FlowchartEditor/useDnD.ts
create mode 100644 apps/web/src/shared/components/FlowchartEditor/useFlowOperations.ts
create mode 100644 apps/web/src/shared/components/FlowchartEditor/useHistory.ts
create mode 100644 apps/web/src/shared/components/FlowchartEditor/useNodeStyles.ts
create mode 100644 apps/web/src/shared/components/FlowchartStatisticsPanel.vue
create mode 100644 apps/web/src/shared/components/Header.vue
create mode 100644 apps/web/src/shared/components/Hitokoto.vue
create mode 100644 apps/web/src/shared/components/IconButton.vue
create mode 100644 apps/web/src/shared/components/Login.vue
create mode 100644 apps/web/src/shared/components/LoginSummaryModal.vue
create mode 100644 apps/web/src/shared/components/MarkdownEditor.vue
create mode 100644 apps/web/src/shared/components/MermaidEditor.vue
create mode 100644 apps/web/src/shared/components/Pagination.vue
create mode 100644 apps/web/src/shared/components/Signup.vue
create mode 100644 apps/web/src/shared/components/StatisticsPanel.vue
create mode 100644 apps/web/src/shared/components/SubmissionResultTag.vue
create mode 100644 apps/web/src/shared/components/SyncCodeEditor.vue
create mode 100644 apps/web/src/shared/components/TextCopy.vue
create mode 100644 apps/web/src/shared/components/TextEditor.vue
create mode 100644 apps/web/src/shared/components/UserBadge.vue
create mode 100644 apps/web/src/shared/composables/breakpoints.ts
create mode 100644 apps/web/src/shared/composables/configUpdate.ts
create mode 100644 apps/web/src/shared/composables/learnProgress.ts
create mode 100644 apps/web/src/shared/composables/maxkb.ts
create mode 100644 apps/web/src/shared/composables/pagination.ts
create mode 100644 apps/web/src/shared/composables/rarity.ts
create mode 100644 apps/web/src/shared/composables/sync.ts
create mode 100644 apps/web/src/shared/composables/useMermaid.ts
create mode 100644 apps/web/src/shared/composables/websocket.ts
create mode 100644 apps/web/src/shared/extensions/autocompletion.ts
create mode 100644 apps/web/src/shared/extensions/baseTheme.ts
create mode 100644 apps/web/src/shared/extensions/c.ts
create mode 100644 apps/web/src/shared/extensions/python.ts
create mode 100644 apps/web/src/shared/extensions/sql.ts
create mode 100644 apps/web/src/shared/layout/admin.vue
create mode 100644 apps/web/src/shared/layout/default.vue
create mode 100644 apps/web/src/shared/store/achievement.ts
create mode 100644 apps/web/src/shared/store/authModal.ts
create mode 100644 apps/web/src/shared/store/config.ts
create mode 100644 apps/web/src/shared/store/loginSummary.ts
create mode 100644 apps/web/src/shared/store/myFlowchart.ts
create mode 100644 apps/web/src/shared/store/screenMode.ts
create mode 100644 apps/web/src/shared/store/user.ts
create mode 100644 apps/web/src/shared/themes/createTheme.ts
create mode 100644 apps/web/src/shared/themes/oneDark.ts
create mode 100644 apps/web/src/shared/themes/smoothy.ts
create mode 100644 apps/web/src/utils/constants.ts
create mode 100644 apps/web/src/utils/download.ts
create mode 100644 apps/web/src/utils/functions.ts
create mode 100644 apps/web/src/utils/http.ts
create mode 100644 apps/web/src/utils/judge.ts
create mode 100644 apps/web/src/utils/permissions.ts
create mode 100644 apps/web/src/utils/renders.ts
create mode 100644 apps/web/src/utils/storage.ts
create mode 100644 apps/web/src/utils/stream.ts
create mode 100644 apps/web/src/utils/types.ts
create mode 100644 apps/web/tests/submitButtonState.test.ts
create mode 100644 apps/web/tsconfig.app.json
create mode 100644 apps/web/tsconfig.json
create mode 100644 apps/web/tsconfig.node.json
create mode 100644 apps/web/vite.config.ts
diff --git a/.gitignore b/.gitignore
index 274dc5b..2561b5b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,9 @@ build/
.env
.env.*
!.env.example
+!apps/web/.env.production
+!apps/web/.env.staging
+!apps/web/.env.test
.DS_Store
.vscode/
diff --git a/apps/web/.browserslistrc b/apps/web/.browserslistrc
new file mode 100644
index 0000000..21e47a5
--- /dev/null
+++ b/apps/web/.browserslistrc
@@ -0,0 +1 @@
+chrome >= 90
diff --git a/apps/web/.env.production b/apps/web/.env.production
new file mode 100644
index 0000000..c19eedf
--- /dev/null
+++ b/apps/web/.env.production
@@ -0,0 +1,8 @@
+PUBLIC_ENV=xuyue.cc
+PUBLIC_MAXKB_URL=https://maxkb.xuyue.cc/chat/api/embed?protocol=https&host=maxkb.xuyue.cc&token=dd37457027c40b39
+PUBLIC_OJ_URL=https://oj.xuyue.cc
+PUBLIC_CODE_URL=https://code.xuyue.cc
+PUBLIC_JUDGE0_URL=https://judge0api.xuyue.cc
+PUBLIC_SIGNALING_URL=wss://signaling.xuyue.cc
+PUBLIC_WS_URL=wss://oj.xuyue.cc/ws
+PUBLIC_ICONIFY_URL=https://icon.xuyue.cc
\ No newline at end of file
diff --git a/apps/web/.env.staging b/apps/web/.env.staging
new file mode 100644
index 0000000..7916890
--- /dev/null
+++ b/apps/web/.env.staging
@@ -0,0 +1,8 @@
+PUBLIC_ENV=school
+PUBLIC_MAXKB_URL=http://10.13.114.114:92/chat/api/embed?protocol=http&host=10.13.114.114:92&token=dd37457027c40b39
+PUBLIC_OJ_URL=http://10.13.114.114:81
+PUBLIC_CODE_URL=http://10.13.114.114:82
+PUBLIC_JUDGE0_URL=http://10.13.114.114:8082
+PUBLIC_ICONIFY_URL=http://10.13.114.114:8098
+PUBLIC_SIGNALING_URL=ws://10.13.114.114:8085
+PUBLIC_WS_URL=ws://10.13.114.114:81/ws
\ No newline at end of file
diff --git a/apps/web/.env.test b/apps/web/.env.test
new file mode 100644
index 0000000..cf7dc87
--- /dev/null
+++ b/apps/web/.env.test
@@ -0,0 +1,8 @@
+PUBLIC_ENV=test
+PUBLIC_MAXKB_URL=http://10.13.114.114:92/chat/api/embed?protocol=http&host=10.13.114.114:92&token=dd37457027c40b39
+PUBLIC_OJ_URL=http://10.13.114.114:93
+PUBLIC_CODE_URL=http://10.13.114.114:82
+PUBLIC_JUDGE0_URL=http://10.13.114.114:8082
+PUBLIC_ICONIFY_URL=http://10.13.114.114:8098
+PUBLIC_SIGNALING_URL=ws://10.13.114.114:8085
+PUBLIC_WS_URL=ws://10.13.114.114:93/ws
\ No newline at end of file
diff --git a/apps/web/.github/workflows/deploy.yml b/apps/web/.github/workflows/deploy.yml
new file mode 100644
index 0000000..79cfa2c
--- /dev/null
+++ b/apps/web/.github/workflows/deploy.yml
@@ -0,0 +1,46 @@
+name: Deploy
+
+on:
+ push:
+ branches:
+ - main
+
+permissions:
+ contents: read
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - name: debian
+ build_command: build
+ remote_port: 22
+ target: /root/OJDeploy/data/clientnext
+ - name: school
+ build_command: build:staging
+ remote_port: 8822
+ target: /root/OJ/data/dist
+ steps:
+ - uses: actions/checkout@v7
+
+ - uses: actions/setup-node@v7
+ with:
+ node-version: 24
+ cache: npm
+ - run: npm install
+ - run: npm run ${{ matrix.build_command }}
+ env:
+ CI: false
+
+ - uses: easingthemes/ssh-deploy@main
+ with:
+ SSH_PRIVATE_KEY: ${{ secrets.KEY }}
+ REMOTE_HOST: ${{ secrets.HOST }}
+ REMOTE_PORT: ${{ matrix.remote_port }}
+ ARGS: "-avzr --delete"
+ SOURCE: dist/
+ REMOTE_USER: root
+ TARGET: ${{ matrix.target }}
\ No newline at end of file
diff --git a/apps/web/.gitignore b/apps/web/.gitignore
new file mode 100644
index 0000000..e0280c2
--- /dev/null
+++ b/apps/web/.gitignore
@@ -0,0 +1,30 @@
+# 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?
+
+src/components.d.ts
+src/auto-imports.d.ts
+
+.claude
+.worktrees
\ No newline at end of file
diff --git a/apps/web/.prettierrc.toml b/apps/web/.prettierrc.toml
new file mode 100644
index 0000000..d165b8d
--- /dev/null
+++ b/apps/web/.prettierrc.toml
@@ -0,0 +1 @@
+semi=false
\ No newline at end of file
diff --git a/apps/web/CLAUDE.md b/apps/web/CLAUDE.md
new file mode 100644
index 0000000..7efe1f5
--- /dev/null
+++ b/apps/web/CLAUDE.md
@@ -0,0 +1,114 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Project Overview
+
+**ojnext** is the frontend for an Online Judge platform. Built with Vue 3 + TypeScript using Vite (Rolldown-based bundler), Naive UI component library, Pinia for state management, and Vue Router.
+
+## Commands
+
+```bash
+npm start # Start dev server on port 5173
+npm run build # Production build
+npm run build:staging # Staging build
+npm run build:test # Test build
+npm fmt # Format with Prettier
+```
+
+No test suite is configured. Linting is via Prettier only.
+
+## Architecture
+
+### Directory Structure
+
+```
+src/
+├── shared/ # Cross-cutting concerns: layout, stores, composables, API
+├── oj/ # User-facing features (problems, submissions, contests, etc.)
+├── admin/ # Admin panel features
+├── utils/ # Constants, types, HTTP client, helpers
+├── routes.ts # Route definitions (two top-level: ojs, admins)
+├── main.ts # App entry point
+└── App.vue # Root component with Naive UI theme setup
+```
+
+### Module Pattern
+
+Each feature module (under `oj/` or `admin/`) typically has:
+- `views/` — page-level Vue components
+- `components/` — feature-specific components
+- `api.ts` — API calls specific to the feature
+
+Shared logic lives in `shared/`:
+- `store/` — Pinia stores: `user` (auth/roles), `config` (site-wide settings), `authModal` (login/signup form state), `screenMode` (problem split-screen layout), `loginSummary` (AI activity summary)
+- `composables/` — `pagination` (URL-synced), `websocket` (reconnect + heartbeat), `sync` (Yjs/y-webrtc for collaborative editing), `configUpdate` (WS-pushed config sync), `useMermaid` (lazy Mermaid render), `breakpoints`, `maxkb`
+- `layout/` — `default.vue` and `admin.vue` layout wrappers
+- `api.ts` — shared API calls (auth, profile, tags, captcha)
+
+### Auto-Imports
+
+Configured via `unplugin-auto-import` and `unplugin-vue-components`. You do **not** need to manually import:
+- Vue APIs (`ref`, `computed`, `watch`, etc.)
+- Vue Router (`useRouter`, `useRoute`)
+- Pinia (`defineStore`, `storeToRefs`)
+- VueUse composables
+- Naive UI composables (`useDialog`, `useMessage`, `useNotification`, `useLoadingBar`)
+- Naive UI components (all `N*` components)
+- Naive UI types (`DataTableColumn`, `FormRules`, `FormItemRule`, `SelectOption`, `UploadCustomRequestOptions`, `UploadFileInfo`, `MenuOption`, `DropdownOption`)
+
+Generated type declaration files: `src/auto-imports.d.ts`, `src/components.d.ts`.
+
+### Path Aliases
+
+```
+utils → ./src/utils
+oj → ./src/oj
+admin → ./src/admin
+shared → ./src/shared
+```
+
+### HTTP Client
+
+`utils/http.ts` — Axios instance with interceptors. All API calls proxy through the dev server:
+- `/api` and `/public` → `PUBLIC_OJ_URL` (backend)
+- `/ws` → `PUBLIC_WS_URL` (WebSocket backend)
+
+### Key Utilities
+
+- `utils/constants.ts` — Judge status codes, language IDs, difficulty levels, contest types
+- `utils/types.ts` — TypeScript interfaces for all domain models
+- `utils/permissions.ts` — Permission check helpers
+- `utils/judge.ts` — Judge-related utilities
+- `utils/renders.ts` — Table column render helpers for Naive UI DataTable
+
+### Environment Variables
+
+Variables prefixed with `PUBLIC_` are injected at build time. Env files: `.env`, `.env.staging`, `.env.test`.
+
+| Variable | Purpose |
+|---|---|
+| `PUBLIC_OJ_URL` | Backend REST API base URL |
+| `PUBLIC_WS_URL` | WebSocket server URL |
+| `PUBLIC_ENV` | Environment name (dev/staging/production) |
+| `PUBLIC_CODE_URL` | Code execution service |
+| `PUBLIC_JUDGE0_URL` | Judge0 API |
+| `PUBLIC_MAXKB_URL` | Knowledge base service |
+| `PUBLIC_SIGNALING_URL` | WebRTC signaling server |
+| `PUBLIC_ICONIFY_URL` | Iconify icon CDN |
+
+### Routing
+
+Routes are defined in `src/routes.ts` with two root routes: `ojs` (user-facing) and `admins` (admin panel). Route meta fields used:
+- `requiresAuth` — redirect to login if not authenticated
+- `requiresSuperAdmin` — super admin only
+- `requiresProblemPermission` — problem management access
+
+### Real-time Features
+
+- WebSocket via composable in `shared/composables/` for submission status updates
+- Yjs + y-webrtc for collaborative editing in the flowchart editor
+
+## Related Repository
+
+The backend is at `../OnlineJudge` — a Django 5 + DRF project. See its CLAUDE.md for backend details.
diff --git a/apps/web/README.md b/apps/web/README.md
new file mode 100644
index 0000000..b18748c
--- /dev/null
+++ b/apps/web/README.md
@@ -0,0 +1 @@
+oj.xuyue.cc
\ No newline at end of file
diff --git a/apps/web/docs/API接口对比分析.md b/apps/web/docs/API接口对比分析.md
new file mode 100644
index 0000000..2a0cb71
--- /dev/null
+++ b/apps/web/docs/API接口对比分析.md
@@ -0,0 +1,548 @@
+# API接口对比分析
+
+## 更新日志
+
+### 最近更新(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),包含特殊规则
+ - 补充了时间范围选择功能
+ - 说明了流式响应的实现方式
+ - 前端组件从 `WeeklyChart.vue` 升级为 `DurationChart.vue`(混合图表)
+- 🔧 **数据缓存优化**:后端AI接口增加了缓存机制,提升性能
+- 🐛 **修正等级系统说明**:更正了等级阈值(A级:前35%,B级:前75%),并补充了小规模参与惩罚规则
+
+---
+
+## 一、前端已使用的API接口
+
+### 1. 用户认证相关(shared/api.ts)
+- `POST /api/login` - 用户登录
+- `POST /api/register` - 用户注册
+- `GET /api/logout` - 用户登出
+- `GET /api/profile` - 获取用户资料
+- `GET /api/captcha` - 获取验证码
+
+### 2. OJ普通用户API(oj/api.ts)
+#### 2.1 网站配置
+- `GET /api/website` - 获取网站配置
+- `GET /api/hitokoto` - 获取一言
+
+#### 2.2 题目相关
+- `GET /api/problem` - 获取题目列表
+- `GET /api/problem` - 获取单个题目
+- `GET /api/problem/tags` - 获取题目标签列表
+- `GET /api/problem/author` - 获取题目作者列表
+- `GET /api/problem/beat_count` - 获取题目击败率
+- `GET /api/pickone` - 随机获取题目
+- `GET /api/contest/problem` - 获取竞赛题目
+
+#### 2.3 提交相关
+- `GET /api/submission` - 获取单个提交
+- `POST /api/submission` - 提交代码
+- `GET /api/submissions` - 获取提交列表
+- `GET /api/submissions/today_count` - 获取今日提交数
+- `GET /api/contest_submissions` - 获取竞赛提交列表
+
+#### 2.4 排名相关
+- `GET /api/user_rank` - 获取用户排名
+- `GET /api/user_activity_rank` - 获取活跃度排名
+- `GET /api/user_problem_rank` - 获取题目排名
+- `GET /api/contest_rank` - 获取竞赛排名
+
+#### 2.5 竞赛相关
+- `GET /api/contests` - 获取竞赛列表
+- `GET /api/contest` - 获取单个竞赛
+- `GET /api/contest/access` - 获取竞赛访问权限
+- `POST /api/contest/password` - 验证竞赛密码
+
+#### 2.6 公告相关
+- `GET /api/announcement` - 获取公告列表/单个公告
+
+#### 2.7 消息相关
+- `POST /api/message` - 创建消息
+- `GET /api/message` - 获取消息列表
+
+#### 2.8 评论相关
+- `POST /api/comment` - 创建评论
+- `GET /api/comment` - 获取评论
+- `GET /api/comment/statistics` - 获取评论统计
+
+#### 2.9 用户相关
+- `POST /api/upload_avatar` - 上传头像
+- `PUT /api/profile` - 更新用户资料
+- `GET /api/profile/fresh_display_id` - 刷新用户题目显示ID
+- `GET /api/metrics` - 获取用户统计数据
+
+#### 2.10 教程相关
+- `GET /api/tutorial` - 获取单个教程
+- `GET /api/tutorials` - 获取教程列表
+
+#### 2.11 AI分析相关
+- `GET /api/ai/detail` - 获取用户详细数据
+ - **参数**: start, end(时间范围)
+ - **返回**: 用户等级(S/A/B/C)、已解决题目列表、标签统计、难度统计、参赛次数等
+ - **特点**: 包含班级排名对比,计算每道题的解题排名和等级
+- `GET /api/ai/duration` - 获取时段数据
+ - **参数**: end(结束时间), duration(时间单位,如 "months:6", "weeks:1")
+ - **返回**: 每周/每月的综合情况(题目数、提交数、等级)
+ - **用途**: 用于绘制时间趋势图,展示学习进度变化
+- `GET /api/ai/heatmap` - 获取热力图数据
+ - **返回**: 用户的提交热力图数据(按日期统计提交数)
+ - **用途**: 可视化用户活跃度分布
+- `POST /api/ai/analysis` - AI智能分析生成
+ - **请求体**: details(详细数据), duration(时段数据)
+ - **响应方式**: 流式响应(Server-Sent Events)
+ - **AI提供商**: DeepSeek
+ - **功能**: 根据用户学习数据生成个性化学习建议和鼓励
+ - **实现**: 使用fetch直接调用,在 `oj/store/ai.ts` 中处理流式输出
+
+### 3. 管理员API(admin/api.ts)
+#### 3.1 仪表板
+- `GET /api/admin/dashboard_info` - 获取仪表板信息
+- `GET /api/admin/random_user` - 随机获取用户
+
+#### 3.2 题目管理
+- `GET /api/admin/problem` - 获取题目列表/单个题目
+- `POST /api/admin/problem` - 创建题目
+- `PUT /api/admin/problem` - 编辑题目
+- `PUT /api/admin/problem/visible` - 切换题目可见性
+- `DELETE /api/admin/problem` - 删除题目
+- `GET /api/admin/contest/problem` - 获取竞赛题目
+- `POST /api/admin/contest/problem` - 创建竞赛题目
+- `PUT /api/admin/contest/problem` - 编辑竞赛题目
+- `DELETE /api/admin/contest/problem` - 删除竞赛题目
+- `POST /api/admin/contest/add_problem_from_public` - 从公开题库添加题目到竞赛
+
+#### 3.3 用户管理
+- `GET /api/admin/user` - 获取用户列表
+- `POST /api/admin/user` - 导入用户
+- `PUT /api/admin/user` - 编辑用户
+- `DELETE /api/admin/user` - 删除用户
+- `POST /api/admin/reset_password` - 重置用户密码
+
+#### 3.4 竞赛管理
+- `GET /api/admin/contest` - 获取竞赛列表/单个竞赛
+- `POST /api/admin/contest` - 创建竞赛
+- `PUT /api/admin/contest` - 编辑竞赛
+- `GET /api/admin/contest/acm_helper` - 获取ACM比赛辅助检查列表
+- `PUT /api/admin/contest/acm_helper` - 更新ACM比赛辅助检查状态
+
+#### 3.5 测试用例管理
+- `POST /api/admin/test_case` - 上传测试用例
+- `GET /api/admin/prune_test_case` - 列出无效测试用例
+- `DELETE /api/admin/prune_test_case` - 清理无效测试用例
+
+#### 3.6 题目管理扩展
+- `POST /api/admin/contest_problem/make_public` - 将竞赛题目转为公开题目
+
+#### 3.7 判题服务器管理
+- `GET /api/admin/judge_server` - 获取判题服务器列表
+- `DELETE /api/admin/judge_server` - 删除判题服务器
+
+#### 3.8 公告管理
+- `GET /api/admin/announcement` - 获取公告列表/单个公告
+- `POST /api/admin/announcement` - 创建公告
+- `PUT /api/admin/announcement` - 编辑公告
+- `DELETE /api/admin/announcement` - 删除公告
+
+#### 3.9 评论管理
+- `GET /api/admin/comment` - 获取评论列表
+- `DELETE /api/admin/comment` - 删除评论
+
+#### 3.10 网站配置
+- `GET /api/admin/website` - 获取网站配置
+- `POST /api/admin/website` - 更新网站配置
+
+#### 3.11 文件上传
+- `POST /api/admin/upload_image` - 上传图片(富文本编辑器、Markdown编辑器使用)
+
+#### 3.12 提交管理
+- `GET /api/admin/submission/rejudge` - 重新判题
+- `GET /api/admin/submission/statistics` - 获取提交统计
+
+#### 3.13 教程管理
+- `GET /api/admin/tutorial` - 获取教程列表/单个教程
+- `POST /api/admin/tutorial` - 创建教程
+- `PUT /api/admin/tutorial` - 更新教程
+- `DELETE /api/admin/tutorial` - 删除教程
+- `PUT /api/admin/tutorial/visibility` - 设置教程可见性
+
+---
+
+## 二、后端提供但前端未使用的API接口
+
+### 1. 用户认证相关(account)
+- `POST /api/change_password` - 修改密码
+- `POST /api/change_email` - 修改邮箱
+- `POST /api/apply_reset_password` - 申请重置密码
+- `POST /api/reset_password` - 重置密码
+- `GET /api/check_username_or_email` - 检查用户名或邮箱是否存在
+- `GET /api/tfa_required` - 检查是否需要双因素认证
+- `POST /api/two_factor_auth` - 双因素认证
+- `GET /api/sessions` - 会话管理
+- `GET /api/open_api_appkey` - OpenAPI密钥管理
+- `GET /api/sso` - 单点登录
+
+### 2. 用户管理(admin)
+- `GET /api/admin/generate_user` - 生成用户
+
+### 3. 网站配置相关
+- `GET /api/languages` - 获取支持的编程语言列表
+
+### 4. 判题服务器内部接口(不需要前端实现)
+- ❌ `POST /api/judge_server_heartbeat/` - 判题服务器心跳
+ - **标记为不需要**
+ - **原因**: 此接口由 JudgeServer Docker 容器调用,用于向后端报告服务器状态
+ - **使用方**: 判题服务器(非前端)
+ - **数据内容**: hostname, judger_version, CPU/内存使用率等
+ - **认证方式**: 使用特殊的 judge_server_token,非用户认证
+
+### 5. 管理员配置相关
+- `GET /api/admin/smtp` - SMTP配置
+- `POST /api/admin/smtp_test` - SMTP测试
+- `GET /api/admin/versions` - 版本信息
+
+### 6. 题目管理相关(admin)
+- `POST /api/admin/export_problem` - 导出题目
+- `POST /api/admin/import_problem` - 导入题目
+- `POST /api/admin/import_fps` - 导入FPS格式题目
+
+### 7. 竞赛相关(admin)
+- `GET /api/contest/announcement` - 获取竞赛公告列表(OJ端)
+- `GET /api/admin/contest/announcement` - 获取竞赛公告(管理端)
+- `GET /api/admin/download_submissions` - 下载竞赛提交
+
+### 8. 提交相关(不必要的接口)
+- ❌ `GET /api/submission_exists` - 检查提交是否存在
+ - **标记为不需要**
+ - **原因**: 题目接口返回的 `my_status` 字段已完整包含此信息
+ - **替代方案**: 直接判断 `my_status` 的值(0=已通过,非零=已尝试未通过,null=未尝试)
+ - **优势**: 零额外请求,性能更优
+
+### 9. 文件上传相关(admin)
+- `POST /api/admin/upload_file` - 上传文件(任意格式)
+ - **说明**: 前端已使用 `upload_image`(仅图片),`upload_file` 可上传任意文件
+ - **当前状态**: 未使用(前端暂无上传非图片文件的需求)
+ - **潜在场景**: 题目附件、教程资料、作业提交等
+
+---
+
+## 三、统计总结
+
+### 前端已使用接口统计
+- **OJ普通用户接口**: 38个(包括1个直接用fetch调用的流式接口)
+- **管理员接口**: 35个
+- **共享接口**: 5个
+- **总计**: 78个API调用
+
+### 后端未被使用接口统计
+- **用户认证相关**: 10个
+- **网站配置相关**: 2个(languages)
+- **题目管理相关**: 3个
+- **竞赛管理相关**: 3个
+- **其他**: 1个
+- **标记为不需要**: 2个
+ - submission_exists(数据冗余)
+ - judge_server_heartbeat(内部接口)
+- **总计**: 21个API端点(其中2个不需要前端实现)
+
+### 未使用接口占比
+约 **21%** 的后端API接口前端尚未使用
+- **需要考虑实现**: 19个接口
+- **不必要实现**: 2个接口(submission_exists, judge_server_heartbeat)
+
+**备注**: 本次更新新增了 ACM 比赛辅助检查功能(2个接口),用于赛后人工审核代码。
+
+---
+
+## 四、建议
+
+### 1. 高优先级需要实现的功能
+- **密码管理**: change_password, apply_reset_password, reset_password
+- **邮箱管理**: change_email
+- **用户名/邮箱检查**: check_username_or_email(注册时实时验证)
+- **编程语言列表**: languages(显示支持的编程语言)
+- **题目导入导出**: export_problem, import_problem(方便题库管理)
+
+### 2. 中等优先级功能
+- **双因素认证**: tfa_required, two_factor_auth(增强安全性)
+- **会话管理**: sessions(多设备登录管理)
+- **竞赛公告**: contest/announcement(OJ端,增强竞赛体验)
+
+### 3. 低优先级功能
+- **SSO单点登录**: sso(如需要集成其他系统)
+- **OpenAPI**: open_api_appkey(如需要开放API)
+- **SMTP配置**: smtp, smtp_test(管理员配置)
+- **版本信息**: versions(显示系统版本)
+- **FPS导入**: import_fps(特定格式题目导入)
+- **文件上传**: upload_file(目前只有图片上传)
+
+### 4. 可选功能
+- **生成用户**: generate_user(批量生成测试用户)
+- **下载提交**: download_submissions(下载竞赛所有提交)
+
+---
+
+## 五、接口使用率分析
+
+| 模块 | 后端提供 | 前端使用 | 使用率 |
+|------|---------|---------|--------|
+| 用户认证 | 17 | 7 | 41% |
+| 题目管理 | 14 | 11 | 79% |
+| 提交管理 | 7 | 6 | 86% |
+| 竞赛管理 | 12 | 9 | 75% |
+| 公告管理 | 4 | 4 | 100% |
+| 评论管理 | 4 | 4 | 100% |
+| 消息管理 | 1 | 1 | 100% |
+| 教程管理 | 4 | 4 | 100% |
+| AI分析 | 4 | 4 | 100% ✅ |
+| 配置管理 | 9 | 3 | 33% ⚠️(1个为内部接口) |
+
+**总体使用率约为 79%**(已实现ACM比赛辅助检查功能,竞赛管理使用率提升至75%)
+
+### 特殊说明
+
+#### 1. AI智能分析功能 ✨
+
+**功能概述**: 基于用户的学习数据,使用DeepSeek AI生成个性化的学习分析报告和建议。
+
+**涉及接口**:
+- `GET /api/ai/detail` - 获取详细学习数据
+- `GET /api/ai/duration` - 获取时段趋势数据
+- `GET /api/ai/heatmap` - 获取活跃度热力图
+- `POST /api/ai/analysis` - 生成AI分析(流式响应)
+
+**前端实现**:
+- **页面**: `src/oj/ai/analysis.vue`
+- **Store**: `src/oj/store/ai.ts`
+- **组件**:
+ - `DurationChart.vue` - 混合图表(柱状图+折线图),展示题目数、提交数、等级变化
+ - `Heatmap.vue` - 提交热力图
+ - `Details.vue` - 详细数据展示
+ - `AI.vue` - AI分析结果展示(Markdown格式)
+
+**时间范围选择**:
+支持多种时间范围:一节课(1小时)、两节课(2小时)、一天、一周、一个月、两个月、半年、一年
+
+**等级系统**:
+- **S级**: 排名前10%(卓越水平,约10%的人)
+- **A级**: 排名前35%(优秀水平,约25%的人)
+- **B级**: 排名前75%(良好水平,约40%的人)
+- **C级**: 75%之后(及格水平,约25%的人)
+- **特殊规则**: 参与人数少于10人时,S级降为A级,A级降为B级(避免因人少而评级虚高)
+
+**流式接口实现**:
+`POST /api/ai/analysis` 使用了**流式响应(Server-Sent Events)**,在 `oj/store/ai.ts` 中直接使用 `fetch` API调用,配合 `consumeJSONEventStream` 工具函数处理流式数据,实现AI内容的实时流式输出。
+
+**数据缓存**:
+为提升性能,后端对 `ai/detail` 和 `ai/duration` 接口的返回数据进行了缓存,相同参数的请求会直接返回缓存结果。
+
+#### 2. ACM 比赛辅助检查功能 ✨
+
+**功能说明**: 用于赛后人工审核 ACM 模式比赛的代码,检查是否存在抄袭、作弊等行为。
+
+**涉及接口**:
+- `GET /api/admin/contest/acm_helper` - 获取比赛中所有 AC 的提交记录
+ - **返回数据**: 用户名、题目ID、AC时间、错误次数、检查状态等
+- `PUT /api/admin/contest/acm_helper` - 更新提交的检查状态
+ - **参数**: contest_id, rank_id, problem_id, checked
+
+**使用场景**:
+1. 管理员进入比赛详情页,点击"审核"按钮进入辅助检查页面
+2. 系统展示所有 AC 提交的列表(按用户和题目分组)
+3. 管理员可以:
+ - 查看每个提交的代码详情
+ - 标记已检查的提交
+ - 批量标记所有提交为已检查
+ - 按用户名、题目、检查状态筛选
+4. 实时显示检查进度统计(总计/已检查/未检查)
+
+**实现位置**:
+- 页面: `src/admin/contest/helper.vue`
+- 路由: `/admin/contest/:contestID/helper`
+- API: `src/admin/api.ts` (getACMHelperList, updateACMHelperChecked)
+
+#### 3. 前端不需要的接口 ❌
+
+##### 3.1 数据冗余接口
+**`GET /api/submission_exists`** - 此接口**无需实现**
+
+**分析结论**:
+- 后端题目接口(`GET /api/problem`)已返回 `my_status` 字段
+- `my_status` 完整记录了用户的做题状态:
+ - `0` (JudgeStatus.ACCEPTED) = 已通过 ✅
+ - `-1` (JudgeStatus.WRONG_ANSWER) = 答案错误 ❌
+ - `-2` (JudgeStatus.COMPILE_ERROR) = 编译错误 ❌
+ - `1` (JudgeStatus.TIME_LIMIT_EXCEEDED) = 超时 ❌
+ - 其他非零值 = 其他失败原因 ❌
+ - `null/undefined` = 从未提交 ⭕
+
+**前端实现**:
+```typescript
+// 仅需一个计算属性即可判断
+const hasTriedButNotPassed = computed(() => {
+ return problem.value?.my_status !== undefined &&
+ problem.value?.my_status !== null &&
+ problem.value?.my_status !== 0
+})
+```
+
+**优势对比**:
+| 方案 | API请求 | 代码复杂度 | 性能 |
+|------|---------|-----------|------|
+| ❌ 使用 submission_exists | +1 | 高(需异步+状态管理) | 慢(额外网络请求) |
+| ✅ 使用 my_status | 0 | 低(3行计算属性) | 快(本地计算) |
+
+**经验教训**:
+- 实现新功能前应充分了解后端现有数据结构
+- 避免创建冗余接口,优先利用现有数据
+- 简单的解决方案往往是最好的
+
+---
+
+##### 3.2 内部系统接口
+**`POST /api/judge_server_heartbeat/`** - 此接口**无需前端实现**
+
+**接口说明**:
+- **用途**: 判题服务器(JudgeServer)向后端报告健康状态
+- **调用方**: JudgeServer Docker 容器(非前端)
+- **调用频率**: 每隔几秒自动调用一次
+- **认证方式**: 使用 `judge_server_token`(特殊令牌,非用户认证)
+
+**报告的数据**:
+```python
+{
+ "hostname": "judge-server-1",
+ "judger_version": "2.0.4",
+ "cpu_core": 4,
+ "cpu": 45.2, # CPU使用率
+ "memory": 60.5, # 内存使用率
+ "service_url": "http://judger:8080"
+}
+```
+
+**后端使用场景**:
+- 监控判题服务器在线状态
+- 显示服务器资源使用情况(仅在管理后台显示)
+- 负载均衡分配判题任务
+
+**前端已有接口**:
+前端查看判题服务器状态使用的是:
+- `GET /api/admin/judge_server` - 获取所有判题服务器列表及状态
+
+**结论**:
+此接口是系统内部通信接口,前端完全不需要调用。类似的内部接口还可能存在于分布式系统的其他服务间通信中。
+
+---
+
+## 六、新增功能模块
+
+### 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/apps/web/docs/FlowchartEditor.md b/apps/web/docs/FlowchartEditor.md
new file mode 100644
index 0000000..e026d3a
--- /dev/null
+++ b/apps/web/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
+
+
Rqe2FE$7DT+B(Yqn s!OwoxF@c&BKxi?J>P0H8V?@mw;o_bJraRmK$28^D<)H?T#NStkj`yFevC%_
zK@TyuCDPU+mhy3F8y5?ZZsz%yEU>RZnS>~MR3C3h7?yi7^5t`OP9AJX7O0|5rjkaInli_%
zT&A*7sGB^Vpfk6rFJMy@rkFF0ZzXekJcfril!z#!k1YD}ah;S-q^wMrfHI4CD{@F7
ztc^-{RuGhmNODRSr;tu?M;Cp5FNB&&eOMuLOdfq>8p)_weupV^fIee<17CjvTzCag
zYXM?{0zX&+U3>vhWdlN811L8D6)XT9JpnB|03tL1JW~KWO#&A;08EJiO=$s3VF6ls
z0u&