重构题目的md显示
Some checks failed
Deploy / deploy (push) Has been cancelled

This commit is contained in:
2025-12-30 23:27:51 +08:00
parent c3c8f6ad4d
commit 00ec146f57
4 changed files with 44 additions and 132 deletions

8
package-lock.json generated
View File

@@ -28,7 +28,7 @@
"date-fns": "^4.1.0",
"fflate": "^0.8.2",
"highlight.js": "^11.11.1",
"md-editor-v3": "^6.2.1",
"md-editor-v3": "^6.3.0",
"mermaid": "^11.12.2",
"naive-ui": "^2.43.2",
"nanoid": "^5.1.6",
@@ -4530,9 +4530,9 @@
}
},
"node_modules/md-editor-v3": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/md-editor-v3/-/md-editor-v3-6.2.1.tgz",
"integrity": "sha512-/9pmLG9qJ1/NmxE5e4aNmGSxWJh4vLVAd0zQ9w52YXe8I7b+xjXAQj7GRZVMxRhB9tXTjY7THiqwrNUy+9r0hQ==",
"version": "6.3.0",
"resolved": "https://registry.npmmirror.com/md-editor-v3/-/md-editor-v3-6.3.0.tgz",
"integrity": "sha512-KvrxFA7YZbrTQ5JH6nTPNnAhfDVAV1uOVUGziyds0+wyCeWL5lbuTXjFmL8/2sILPw2v0VPxCEw7SMTlUQmvzg==",
"license": "MIT",
"dependencies": {
"@codemirror/autocomplete": "^6.18.7",

View File

@@ -3,7 +3,7 @@
"version": "1.8.0",
"type": "module",
"scripts": {
"start": "rsbuild dev",
"start": "rsbuild dev --env-mode=production",
"build": "rsbuild build",
"build:staging": "rsbuild build --env-mode=staging",
"build:test": "rsbuild build --env-mode=test",
@@ -30,7 +30,7 @@
"date-fns": "^4.1.0",
"fflate": "^0.8.2",
"highlight.js": "^11.11.1",
"md-editor-v3": "^6.2.1",
"md-editor-v3": "^6.3.0",
"mermaid": "^11.12.2",
"naive-ui": "^2.43.2",
"nanoid": "^5.1.6",

View File

@@ -1,3 +1,11 @@
body {
height: 100vh;
}
.md-editor-dark {
--md-bk-color: var(--n-body-color) !important;
}
.md-editor-dark div.vuepress-theme {
--md-theme-color: var(--n-text-color) !important;
}

View File

@@ -7,6 +7,9 @@ import { useProblemStore } from "oj/store/problem"
import { createTestSubmission } from "utils/judge"
import { Problem, ProblemStatus } from "utils/types"
import Copy from "shared/components/Copy.vue"
import { useDark } from "@vueuse/core"
import { MdPreview } from "md-editor-v3"
import "md-editor-v3/lib/preview.css"
type Sample = Problem["samples"][number] & {
id: number
@@ -17,7 +20,7 @@ type Sample = Problem["samples"][number] & {
const theme = useThemeVars()
const style = computed(() => "color: " + theme.value.primaryColor)
const isDark = useDark()
const route = useRoute()
const codeStore = useCodeStore()
const problemStore = useProblemStore()
@@ -25,10 +28,6 @@ const { problem } = storeToRefs(problemStore)
const problemSetId = computed(() => route.params.problemSetId)
// 判断用户是否尝试过但未通过
// my_status === 0: 已通过
// my_status !== 0 && my_status !== null: 尝试过但未通过
// my_status === null: 从未尝试
const hasTriedButNotPassed = computed(() => {
return (
problem.value?.my_status !== undefined &&
@@ -108,7 +107,7 @@ function type(status: ProblemStatus) {
</script>
<template>
<div v-if="problem" class="problemContent">
<div v-if="problem">
<template v-if="!problemSetId">
<!-- 已通过 -->
<n-alert
@@ -140,7 +139,11 @@ function type(status: ProblemStatus) {
描述
</n-flex>
</p>
<div class="content" v-html="problem.description"></div>
<MdPreview
preview-theme="vuepress"
:model-value="problem.description"
:theme="isDark ? 'dark' : 'light'"
/>
<p class="title" :style="style">
<n-flex align="center">
@@ -148,7 +151,11 @@ function type(status: ProblemStatus) {
输入
</n-flex>
</p>
<div class="content" v-html="problem.input_description"></div>
<MdPreview
preview-theme="vuepress"
:model-value="problem.input_description"
:theme="isDark ? 'dark' : 'light'"
/>
<p class="title" :style="style">
<n-flex align="center">
@@ -156,7 +163,11 @@ function type(status: ProblemStatus) {
输出
</n-flex>
</p>
<div class="content" v-html="problem.output_description"></div>
<MdPreview
preview-theme="vuepress"
:model-value="problem.output_description"
:theme="isDark ? 'dark' : 'light'"
/>
<div v-if="problem.hint">
<p class="title" :style="style">
@@ -165,7 +176,11 @@ function type(status: ProblemStatus) {
提示
</n-flex>
</p>
<div class="content" v-html="problem.hint"></div>
<MdPreview
preview-theme="preview"
:model-value="problem.hint"
:theme="isDark ? 'dark' : 'light'"
/>
</div>
<div v-for="(sample, index) of samples" :key="index">
@@ -210,25 +225,16 @@ function type(status: ProblemStatus) {
<div v-if="problem.source">
<p class="title" :style="style">来源</p>
<div class="content" v-html="problem.source"></div>
<MdPreview
preview-theme="vuepress"
:model-value="problem.source"
:theme="isDark ? 'dark' : 'light'"
/>
</div>
</div>
</template>
<style scoped>
.problemContent {
--border-color-light: rgb(239, 239, 245);
--bg-code-light: rgb(250, 250, 252);
--bg-code-dark: rgb(24, 24, 28);
--bg-table-light: rgba(250, 250, 252, 1);
--bg-table-dark: rgba(38, 38, 42, 1);
--border-color-dark: rgba(255, 255, 255, 0.09);
--blockquote-color: #7b7b7b;
--blockquote-border: #bbbec4;
--link-color: #18a058;
--transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.problemTitle {
margin: 0;
}
@@ -247,106 +253,4 @@ function type(status: ProblemStatus) {
.status-alert {
margin-bottom: 16px;
}
.content {
font-size: 16px;
line-height: 2;
}
/* 针对 v-html 渲染内容的深度样式 */
.content :deep(p) {
margin: 0;
}
.content :deep(blockquote) {
border-left: 3px solid var(--blockquote-border);
padding-left: 10px;
margin: 10px 0;
color: var(--blockquote-color);
}
.content :deep(pre) {
width: 100%;
background-color: var(--bg-code-light);
border: 1px solid var(--border-color-light);
word-break: break-word;
box-sizing: border-box;
transition:
background-color var(--transition),
border-color var(--transition);
}
.content :deep(pre code) {
font-family: "Monaco", monospace;
}
.dark .content :deep(pre) {
background-color: var(--bg-code-dark);
border-color: var(--border-color-dark);
}
.content :deep(table) {
width: 100%;
border-spacing: 0;
border: 1px solid var(--border-color-light);
transition:
background-color var(--transition),
border-color var(--transition);
}
.content :deep(table th) {
background-color: var(--bg-table-light);
padding: 8px;
transition:
background-color var(--transition),
border-color var(--transition);
}
.dark .content :deep(table th) {
background-color: var(--bg-table-dark);
}
.content :deep(table td) {
padding: 8px;
}
.content :deep(table td),
.content :deep(table th) {
border-right: 1px solid var(--border-color-light);
border-bottom: 1px solid var(--border-color-light);
}
.content :deep(table th:last-child),
.content :deep(table td:last-child) {
border-right: none;
}
.content :deep(table tr:last-child td) {
border-bottom: none;
}
.content :deep(p code) {
font-size: 90%;
padding: 2px 5px;
margin: 0 4px;
background-color: rgba(27, 31, 35, 0.05);
border-radius: 3px;
line-height: 1.5;
font-family: "Monaco", monospace;
}
.content :deep(img) {
max-width: 100%;
height: auto !important;
}
.content :deep(a) {
color: var(--link-color);
text-decoration: none;
transition: opacity var(--transition);
}
.content :deep(a:hover) {
opacity: 0.8;
}
</style>