perf(Markdown): 题面、教程、AI 提示每次打开都去 unpkg.com 拉四个库,机房网络下又慢又不稳
md-editor-v3 的 MdPreview 不管正文里有没有代码、公式,都会从 unpkg.com 加载 highlight.js、katex、mermaid、echarts(mermaid 还是另一份 11.x)。而我们只用到最基础的 Markdown:题面 95% 是富文本存的 HTML,教程是标题、表格、图片,AI 输出是标题、列表、 表格、少量代码块,库里一处公式、mermaid 都没有。 - 显示:新组件 shared/components/Markdown.vue,直接用 markdown-it,代码高亮走本地的 highlight.js(和练一练共用 shared/highlight.ts,补了 C++ / SQL)。9 处 MdPreview 全换掉。 正文默认 16px,教程也统一成 16px。 - 编辑:后台教程编辑器换成项目已有的 CodeMirror,加一排格式按钮;图片可以按按钮选、 粘贴、拖进来,都是先上传再插入。md-editor-v3 从依赖里删掉。 - AI 生成的内容(AI 提示、AI 分析、班级报告)不再放行原生 HTML:学生能在代码里诱导 AI 吐出 <img onerror>,老师在后台一打开就执行。库里 1196 条 AI 输出没有一个 HTML 标签,关掉不影响显示。题面、教程照旧放行。 - 长英文改成在单词之间折行,原来 break-all 会把 "I live" 断成 "I l / ive"。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c497ccadc8
commit
6f47ad8358
24 files changed
+504
-308
No files matched your search
@@ -53,7 +53,7 @@
|
||||
</n-descriptions-item>
|
||||
</n-descriptions>
|
||||
<n-scrollbar style="max-height: 60vh; margin-top: 12px">
|
||||
<MdPreview :model-value="detail.analysis" />
|
||||
<Markdown :content="detail.analysis" />
|
||||
</n-scrollbar>
|
||||
</div>
|
||||
</n-spin>
|
||||
@@ -62,8 +62,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import PageHeader from "admin/components/PageHeader.vue"
|
||||
import { MdPreview } from "md-editor-v3"
|
||||
import "md-editor-v3/lib/preview.css"
|
||||
import Markdown from "shared/components/Markdown.vue"
|
||||
import Pagination from "shared/components/Pagination.vue"
|
||||
import { parseTime } from "utils/functions"
|
||||
import { getAIReportList, getAIReportDetail, pinAIReport, getPinnedAIReports } from "../api"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { EditorView } from "@codemirror/view"
|
||||
import { PROBLEM_TAG_MAX_LENGTH, TEST_CASE_MAX_CASES } from "@oj2/contract"
|
||||
import { MdPreview } from "md-editor-v3"
|
||||
import "md-editor-v3/lib/preview.css"
|
||||
import Markdown from "shared/components/Markdown.vue"
|
||||
import { StorageSerializers } from "@vueuse/core"
|
||||
import { useThemeVars } from "naive-ui"
|
||||
import PageHeader from "admin/components/PageHeader.vue"
|
||||
@@ -56,7 +55,6 @@ const message = useMessage()
|
||||
const router = useRouter()
|
||||
const theme = useThemeVars()
|
||||
const previewCollapsed = usePreviewCollapsed()
|
||||
const isDark = useDark()
|
||||
|
||||
const isCreate = computed(() => !props.problemID)
|
||||
|
||||
@@ -680,11 +678,7 @@ onMounted(async () => {
|
||||
</n-tag>
|
||||
</div>
|
||||
<h3 class="title">描述</h3>
|
||||
<MdPreview
|
||||
preview-theme="vuepress"
|
||||
:model-value="form.description"
|
||||
:theme="isDark ? 'dark' : 'light'"
|
||||
/>
|
||||
<Markdown html :content="form.description" />
|
||||
<p v-if="selected > 0" class="otherGroup">
|
||||
学生看到的是第 1 组,下面是第 {{ selected + 1 }} 组跑出来的样子
|
||||
</p>
|
||||
@@ -720,11 +714,7 @@ onMounted(async () => {
|
||||
</template>
|
||||
<template v-if="!isBlankHtml(form.hint)">
|
||||
<h3 class="title sqlTitle">提示</h3>
|
||||
<MdPreview
|
||||
preview-theme="vuepress"
|
||||
:model-value="form.hint"
|
||||
:theme="isDark ? 'dark' : 'light'"
|
||||
/>
|
||||
<Markdown html :content="form.hint" />
|
||||
</template>
|
||||
</div>
|
||||
</aside>
|
||||
@@ -1003,14 +993,6 @@ onMounted(async () => {
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.page :deep(.md-editor) {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.page :deep(.md-editor-preview-wrapper) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.otherGroup {
|
||||
margin: 14px 0 0;
|
||||
padding: 6px 10px;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { MdPreview } from "md-editor-v3"
|
||||
import "md-editor-v3/lib/preview.css"
|
||||
import Markdown from "shared/components/Markdown.vue"
|
||||
import { useThemeVars } from "naive-ui"
|
||||
import { useMermaid } from "shared/composables/useMermaid"
|
||||
import { DIFFICULTY, SOURCES } from "utils/constants"
|
||||
@@ -42,7 +41,6 @@ const tab = defineModel<PreviewTab>("tab", { required: true })
|
||||
const emit = defineEmits<{ renderState: [ok: boolean]; collapse: [] }>()
|
||||
|
||||
const theme = useThemeVars()
|
||||
const isDark = useDark()
|
||||
|
||||
const isBlankHtml = (html: string) => !html.trim() || html === "<p><br></p>"
|
||||
|
||||
@@ -154,30 +152,17 @@ onMounted(() => nextTick(render))
|
||||
</div>
|
||||
|
||||
<h3 class="title">描述</h3>
|
||||
<MdPreview
|
||||
v-if="!isBlankHtml(description)"
|
||||
preview-theme="vuepress"
|
||||
:model-value="description"
|
||||
:theme="isDark ? 'dark' : 'light'"
|
||||
/>
|
||||
<Markdown html v-if="!isBlankHtml(description)" :content="description" />
|
||||
<p v-else class="placeholder">(还没写描述)</p>
|
||||
|
||||
<div class="io">
|
||||
<section>
|
||||
<h3 class="title">输入</h3>
|
||||
<MdPreview
|
||||
preview-theme="vuepress"
|
||||
:model-value="inputDescription"
|
||||
:theme="isDark ? 'dark' : 'light'"
|
||||
/>
|
||||
<Markdown html :content="inputDescription" />
|
||||
</section>
|
||||
<section>
|
||||
<h3 class="title">输出</h3>
|
||||
<MdPreview
|
||||
preview-theme="vuepress"
|
||||
:model-value="outputDescription"
|
||||
:theme="isDark ? 'dark' : 'light'"
|
||||
/>
|
||||
<Markdown html :content="outputDescription" />
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -207,11 +192,7 @@ onMounted(() => nextTick(render))
|
||||
|
||||
<template v-if="!isBlankHtml(hint)">
|
||||
<h3 class="title">提示</h3>
|
||||
<MdPreview
|
||||
preview-theme="vuepress"
|
||||
:model-value="hint"
|
||||
:theme="isDark ? 'dark' : 'light'"
|
||||
/>
|
||||
<Markdown html :content="hint" />
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@@ -347,14 +328,6 @@ onMounted(() => nextTick(render))
|
||||
border-left: 3px solid v-bind("theme.primaryColor");
|
||||
}
|
||||
|
||||
.page :deep(.md-editor) {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.page :deep(.md-editor-preview-wrapper) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.io {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
|
||||
@@ -203,7 +203,7 @@ onMounted(init)
|
||||
<MarkdownEditor
|
||||
ref="editor"
|
||||
v-model:value="tutorial.content"
|
||||
:preview="false"
|
||||
:code-lang="tutorial.type"
|
||||
height="100%"
|
||||
/>
|
||||
</div>
|
||||
@@ -340,10 +340,6 @@ onMounted(init)
|
||||
min-width: 0;
|
||||
border-right: 1px solid rgba(128, 128, 128, 0.22);
|
||||
}
|
||||
.source :deep(.md-editor) {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.preview {
|
||||
flex: 0 0 50%;
|
||||
min-width: 0;
|
||||
|
||||
Reference in new issue
Block a user