feat(题目页): 手机上写代码顺手多了:键盘上面多一排常用符号(括号、引号、冒号、缩进…点一下就进去,括号自动配对),代码字号改小、长行折行不再看不见右半截;输入输出说明上下排、例子不再被左边两列标签挤窄;题单里那条不再超出屏幕
Deploy / deploy (push) Canceled after 0s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-13 22:56:02 +08:00
1 parent 3dbdc7cb1b
commit 7e68e11371
13 files changed
+262 -16

No files matched your search

@@ -10,7 +10,7 @@ import { explainRuntimeError } from "oj/problem/utils/runtimeError"
import { useAuthModalStore } from "shared/store/authModal"
import { useUserStore } from "shared/store/user"
import { mainWrapExtensions, wrapMain } from "../wrapMain"
import { hangWrapExtensions } from "../hangIndent"
import { hangWrapExtensions } from "shared/extensions/hangIndent"
import { useBreakpoints } from "shared/composables/breakpoints"
const CodeEditor = defineAsyncComponent(() => import("shared/components/CodeEditor.vue"))
@@ -2,7 +2,7 @@
import ExerciseResult from "./ExerciseResult.vue"
import type { Exercise, ExerciseDebugData } from "utils/types"
import { highlightLines } from "shared/highlight"
import { hangStyle } from "../hangIndent"
import { hangStyle } from "shared/extensions/hangIndent"
const props = defineProps<{ exercise: Exercise; lang?: string }>()
const emit = defineEmits<{
@@ -2,7 +2,7 @@
import ExerciseResult from "./ExerciseResult.vue"
import type { Exercise, ExerciseFillData } from "utils/types"
import { highlightWithHoles } from "shared/highlight"
import { hangStyle } from "../hangIndent"
import { hangStyle } from "shared/extensions/hangIndent"
const props = defineProps<{ exercise: Exercise; lang?: string }>()
const emit = defineEmits<{
@@ -4,7 +4,7 @@ import type { Exercise, ExerciseSortData } from "utils/types"
import { shuffle } from "../composables/useShuffle"
import { highlightLines } from "shared/highlight"
import { useBreakpoints } from "shared/composables/breakpoints"
import { hangStyle } from "../hangIndent"
import { hangStyle } from "shared/extensions/hangIndent"
const props = defineProps<{ exercise: Exercise; lang?: string }>()
const emit = defineEmits<{
-78
View File
@@ -1,78 +0,0 @@
import { RangeSetBuilder } from "@codemirror/state"
import {
Decoration,
type DecorationSet,
EditorView,
ViewPlugin,
type ViewUpdate,
} from "@codemirror/view"
/**
* 手机上代码折行。原来是横着滚,可没有滚动条也看不出右边还有,
* 综合练习那种长 print 整整半行看不见。折下来的那截缩到这一行的代码下面再进两格,
* 一眼看得出还是同一行。
*/
/** 行首空白占几格,tab 按 4 */
function leadingWidth(text: string): number {
let width = 0
for (const ch of text) {
if (ch === " ") width++
else if (ch === "\t") width += 4
else break
}
return width
}
/** 静态的代码行(练一练的排序、找错、填空):折行,接着的那截悬挂缩进 */
export function hangStyle(text: string): Record<string, string> {
const width = leadingWidth(text) + 2
return {
whiteSpace: "pre-wrap",
// 中文连着的一串别从中间断(「类」「型」各在一行),实在放不下才随便断
wordBreak: "keep-all",
overflowWrap: "anywhere",
paddingLeft: `${width}ch`,
textIndent: `-${width}ch`,
}
}
function hangDecorations(view: EditorView): DecorationSet {
const builder = new RangeSetBuilder<Decoration>()
for (const { from, to } of view.visibleRanges) {
for (let pos = from; pos <= to;) {
const line = view.state.doc.lineAt(pos)
const width = leadingWidth(line.text) + 2
// 6px 是 CodeMirror 给 .cm-line 的左内边距,盖掉了要补回来
builder.add(
line.from,
line.from,
Decoration.line({
attributes: {
style: `padding-left: calc(${width}ch + 6px); text-indent: -${width}ch; word-break: keep-all; overflow-wrap: anywhere`,
},
}),
)
pos = line.to + 1
}
}
return builder.finish()
}
const hangPlugin = ViewPlugin.fromClass(
class {
decorations: DecorationSet
constructor(view: EditorView) {
this.decorations = hangDecorations(view)
}
update(update: ViewUpdate) {
if (update.docChanged || update.viewportChanged) {
this.decorations = hangDecorations(update.view)
}
}
},
{ decorations: (plugin) => plugin.decorations },
)
/** 编辑器(正文里能运行的代码块):折行 + 悬挂缩进 */
export const hangWrapExtensions = [EditorView.lineWrapping, hangPlugin]