显示流程图
Some checks failed
Deploy / deploy (push) Has been cancelled

This commit is contained in:
2025-10-12 12:59:38 +08:00
parent d7316d4681
commit d3694a8d28
12 changed files with 2659 additions and 90 deletions

View File

@@ -0,0 +1,64 @@
<script setup lang="ts">
import { useProblemStore } from "oj/store/problem"
import { nanoid } from "nanoid"
const problemStore = useProblemStore()
const { problem } = storeToRefs(problemStore)
const mermaidContainer = useTemplateRef<HTMLElement>("mermaidContainer")
// 动态导入 mermaid
let mermaid: any = null
// 动态加载 Mermaid
const loadMermaid = async () => {
if (!mermaid) {
const mermaidModule = await import("mermaid")
mermaid = mermaidModule.default
mermaid.initialize({
startOnLoad: false,
securityLevel: "loose",
theme: "default",
flowchart: {
useMaxWidth: true,
htmlLabels: true,
curve: "basis",
},
sequence: {
useMaxWidth: true,
},
gantt: {
useMaxWidth: true,
},
})
}
return mermaid
}
// 初始化Mermaid并渲染
onMounted(async () => {
// 确保 mermaid 已加载
await loadMermaid()
// 渲染流程图
if (mermaidContainer.value && problem.value?.mermaid_code) {
const id = `mermaid-${nanoid()}`
const { svg } = await mermaid.render(id, problem.value.mermaid_code)
mermaidContainer.value.innerHTML = svg
}
})
</script>
<template>
<div ref="mermaidContainer" class="container"></div>
</template>
<style scoped>
.container {
width: 100%;
max-width: 100%;
min-height: 300px;
display: flex;
justify-content: center;
align-items: center;
}
</style>

View File

@@ -26,6 +26,9 @@ const ProblemSubmission = defineAsyncComponent(
const ProblemComment = defineAsyncComponent(
() => import("./components/ProblemComment.vue"),
)
const ProblemFlowchart = defineAsyncComponent(
() => import("./components/ProblemFlowchart.vue"),
)
interface Props {
problemID: string
@@ -49,6 +52,9 @@ const { isMobile, isDesktop } = useBreakpoints()
const tabOptions = computed(() => {
const options: string[] = ["content"]
if (problem.value?.show_flowchart) {
options.push("flowchart")
}
if (isMobile.value) {
options.push("editor")
}
@@ -115,6 +121,13 @@ watch(isMobile, (value) => {
<n-tab-pane name="content" tab="题目描述">
<ProblemContent />
</n-tab-pane>
<n-tab-pane
v-if="problem.show_flowchart"
name="flowchart"
tab="流程图表"
>
<ProblemFlowchart />
</n-tab-pane>
<n-tab-pane name="info" tab="题目统计">
<ProblemInfo />
</n-tab-pane>
@@ -130,7 +143,10 @@ watch(isMobile, (value) => {
<n-tab-pane name="content" tab="描述">
<ProblemContent />
</n-tab-pane>
<n-tab-pane name="editor" tab="编辑">
<n-tab-pane v-if="problem.show_flowchart" name="flowchart" tab="流程">
<ProblemFlowchart />
</n-tab-pane>
<n-tab-pane name="editor" tab="代码">
<ProblemEditor v-if="shouldUseProblemEditor" />
<ContestEditor v-else />
</n-tab-pane>