From d2b8a1ce4a083c57826c1726fcf989be22b7b1c4 Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Mon, 12 Oct 2026 20:22:39 +0800 Subject: [PATCH] =?UTF-8?q?refactor(=E7=BC=96=E8=BE=91=E5=99=A8):=20?= =?UTF-8?q?=E5=8E=BB=E6=8E=89=20vue-codemirror=EF=BC=8C=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=99=A8=E3=80=81=E5=8D=8F=E4=BD=9C=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=99=A8=E3=80=81=E6=95=99=E7=A8=8B=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=99=A8=E6=94=B9=E7=94=A8=E8=87=AA=E5=B7=B1=E7=9A=84=E8=96=84?= =?UTF-8?q?=E5=A4=96=E5=A3=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 三个编辑器只用到它的 v-model、extensions、只读、缩进、占位文字、尺寸和 ready, shared/components/CodeMirror.vue 照它的做法写了这几样,功能和手感不变: - 它默认带的 basicSetup(行号、撤销、折叠、搜索、括号……)照样带上 - 各项配置的先后顺序和它一致;外部改代码仍是一次不带 userEvent 的 changes, 提交时的编辑过程统计不受影响 - @codemirror/commands 现在直接 import,显式声明进依赖 Co-Authored-By: Claude Opus 5.5 --- apps/web/package.json | 2 +- apps/web/src/oj/problem/utils/editTrace.ts | 2 +- apps/web/src/shared/components/CodeEditor.vue | 8 +- apps/web/src/shared/components/CodeMirror.vue | 115 ++++++++++++++++++ .../src/shared/components/MarkdownEditor.vue | 8 +- .../src/shared/components/SyncCodeEditor.vue | 18 ++- bun.lock | 4 +- 7 files changed, 133 insertions(+), 24 deletions(-) create mode 100644 apps/web/src/shared/components/CodeMirror.vue diff --git a/apps/web/package.json b/apps/web/package.json index 6071b83..b2369a0 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@codemirror/autocomplete": "^6.20.3", + "@codemirror/commands": "^6.10.4", "@codemirror/lang-cpp": "^6.0.3", "@codemirror/lang-markdown": "^6.5.2", "@codemirror/lang-python": "^6.2.1", @@ -47,7 +48,6 @@ "pinyin-pro": "^3.29.5", "vue": "^3.5.43", "vue-chartjs": "^5.3.4", - "vue-codemirror": "^6.1.1", "vue-router": "^5.4.0", "y-codemirror.next": "^0.3.6", "y-protocols": "1.0.7", diff --git a/apps/web/src/oj/problem/utils/editTrace.ts b/apps/web/src/oj/problem/utils/editTrace.ts index 1459d17..efbc5a2 100644 --- a/apps/web/src/oj/problem/utils/editTrace.ts +++ b/apps/web/src/oj/problem/utils/editTrace.ts @@ -11,7 +11,7 @@ import type { SubmissionTrace } from "@oj2/contract" * 直接失效。计数本身也不需要响应式。 * * **只数带 userEvent 的事务。** 下面这些都不带,所以天然不会被算进去: - * - `codeStore.setCode()` —— vue-codemirror 的 setDoc 只 dispatch 一个 changes: + * - `codeStore.setCode()` —— shared/components/CodeMirror.vue 同步 v-model 时只 dispatch 一个 changes: * 提交前的自动格式化、载入草稿 / 模板、切语言都走这条; * - 课堂协作里对方的改动 —— y-codemirror.next 应用远程更新时只挂 ySyncAnnotation。 * diff --git a/apps/web/src/shared/components/CodeEditor.vue b/apps/web/src/shared/components/CodeEditor.vue index 1710124..65846a3 100644 --- a/apps/web/src/shared/components/CodeEditor.vue +++ b/apps/web/src/shared/components/CodeEditor.vue @@ -3,7 +3,7 @@ import { cpp } from "@codemirror/lang-cpp" import { python } from "@codemirror/lang-python" import { sql, SQLite } from "@codemirror/lang-sql" import { bracketMatching } from "@codemirror/language" -import { Codemirror } from "vue-codemirror" +import CodeMirror from "./CodeMirror.vue" import type { Extension } from "@codemirror/state" import { autocompletion, closeBrackets, completeAnyWord } from "@codemirror/autocomplete" import type { LANGUAGE } from "utils/types" @@ -53,13 +53,13 @@ const extensions = computed(() => [ diff --git a/apps/web/src/shared/components/CodeMirror.vue b/apps/web/src/shared/components/CodeMirror.vue new file mode 100644 index 0000000..bc1530c --- /dev/null +++ b/apps/web/src/shared/components/CodeMirror.vue @@ -0,0 +1,115 @@ + + + diff --git a/apps/web/src/shared/components/MarkdownEditor.vue b/apps/web/src/shared/components/MarkdownEditor.vue index b59dc21..205d0e8 100644 --- a/apps/web/src/shared/components/MarkdownEditor.vue +++ b/apps/web/src/shared/components/MarkdownEditor.vue @@ -3,7 +3,7 @@ import { markdown } from "@codemirror/lang-markdown" import { EditorSelection } from "@codemirror/state" import { EditorView, keymap } from "@codemirror/view" import { Icon } from "@iconify/vue" -import { Codemirror } from "vue-codemirror" +import CodeMirror from "./CodeMirror.vue" import { uploadImage } from "../../admin/api" import { styleTheme } from "../extensions/baseTheme" import { oneDark } from "../themes/oneDark" @@ -196,12 +196,12 @@ const tools = computed(() => [
-
diff --git a/apps/web/src/shared/components/SyncCodeEditor.vue b/apps/web/src/shared/components/SyncCodeEditor.vue index 37da3c2..7f6691a 100644 --- a/apps/web/src/shared/components/SyncCodeEditor.vue +++ b/apps/web/src/shared/components/SyncCodeEditor.vue @@ -1,6 +1,6 @@ diff --git a/bun.lock b/bun.lock index 5805b04..30b3045 100644 --- a/bun.lock +++ b/bun.lock @@ -41,6 +41,7 @@ "version": "1.9.0", "dependencies": { "@codemirror/autocomplete": "^6.20.3", + "@codemirror/commands": "^6.10.4", "@codemirror/lang-cpp": "^6.0.3", "@codemirror/lang-markdown": "^6.5.2", "@codemirror/lang-python": "^6.2.1", @@ -76,7 +77,6 @@ "pinyin-pro": "^3.29.5", "vue": "^3.5.43", "vue-chartjs": "^5.3.4", - "vue-codemirror": "^6.1.1", "vue-router": "^5.4.0", "y-codemirror.next": "^0.3.6", "y-protocols": "1.0.7", @@ -1565,8 +1565,6 @@ "vue-chartjs": ["vue-chartjs@5.3.4", "https://registry.npmjs.com/vue-chartjs/-/vue-chartjs-5.3.4.tgz", { "peerDependencies": { "chart.js": "^4.1.1", "vue": "^3.0.0-0 || ^2.7.0" } }, "sha512-x3Fqob8RQvrTdssfi9ecsCzEkFOd8JPmNwSkSQzdfKj/uBsRJs/Y88cZcZIEcPsTVfMGwMo4MOoihoDG2DoE/g=="], - "vue-codemirror": ["vue-codemirror@6.1.1", "https://registry.npmjs.com/vue-codemirror/-/vue-codemirror-6.1.1.tgz", { "dependencies": { "@codemirror/commands": "6.x", "@codemirror/language": "6.x", "@codemirror/state": "6.x", "@codemirror/view": "6.x" }, "peerDependencies": { "codemirror": "6.x", "vue": "3.x" } }, "sha512-rTAYo44owd282yVxKtJtnOi7ERAcXTeviwoPXjIc6K/IQYUsoDkzPvw/JDFtSP6T7Cz/2g3EHaEyeyaQCKoDMg=="], - "vue-demi": ["vue-demi@0.14.10", "https://registry.npmjs.com/vue-demi/-/vue-demi-0.14.10.tgz", { "peerDependencies": { "@vue/composition-api": "^1.0.0-rc.1", "vue": "^3.0.0-0 || ^2.6.0" }, "optionalPeers": ["@vue/composition-api"], "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-switch": "bin/vue-demi-switch.js" } }, "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg=="], "vue-router": ["vue-router@5.4.0", "https://registry.npmjs.com/vue-router/-/vue-router-5.4.0.tgz", { "dependencies": { "@vue-macros/common": "^3.1.3", "@vue/devtools-api": "^8.1.5", "ast-walker-scope": "^0.10.0", "chokidar": "^5.0.0", "confbox": "^0.3.1", "local-pkg": "^1.2.1", "magic-string": "^1.4.3", "mlly": "^1.8.2", "muggle-string": "^0.4.1", "nostics": "^1.3.0", "pathe": "^2.0.3", "picomatch": "^4.0.7", "scule": "^1.3.0", "tinyglobby": "^0.2.17", "unplugin": "^3.4.0", "unplugin-utils": "^0.3.2" }, "peerDependencies": { "@pinia/colada": ">=0.21.2", "@vue/compiler-sfc": "^3.5.34 || ^4.0.0", "pinia": "^3.0.4 || ^4.0.2", "vite": "^7.3.0 || ^8.0.0", "vue": "^3.5.34 || ^4.0.0" }, "optionalPeers": ["@pinia/colada", "@vue/compiler-sfc", "pinia", "vite"] }, "sha512-pFvcYcxinDHjZUlf7AzFBrT8r8Xqvv4uMHoJnjc+EqPawXQvHTkF8S4tfSmQLpriVHUGfkaKlI7Et0KRjTMTdw=="],