fix(frontend): 版本对比左栏不显示——根因monaco 0.56 createDiffEditor在抽屉嵌套容器里分栏测量错误(original栏恒被压36px;时序延迟挂载/layout强制重算/禁拖拽分栏/内联模式四招全试均无效,实测panes 36/748);换双只读编辑器并排各50%(快照|当前,带栏头标签+滚动联动),复用主编辑器同款主题;showDiff延迟360ms等抽屉动画后挂载(容器全宽创建);dev实测panes 408/407左右内容正确 [nas]
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
// 版本 diff 视图(§12.6 代码快照查看):左=历史版本 右=当前代码。
|
||||
// 主题与 MonacoEditor.vue 同名同值(define 幂等,两处挂载互不干扰)。
|
||||
// 版本对比视图(§12.6 代码快照查看):左=历史快照 右=当前代码,各 50% 只读。
|
||||
// 不用 monaco createDiffEditor:0.56 在抽屉等嵌套容器里分栏测量错误
|
||||
// (original 栏被压 ~36px,layout/固定分栏/内联模式均救不回),双只读编辑器最稳。
|
||||
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
|
||||
import * as monaco from 'monaco-editor'
|
||||
|
||||
@@ -17,11 +18,23 @@ const props = withDefaults(defineProps<{
|
||||
language?: string
|
||||
}>(), { language: 'python' })
|
||||
|
||||
const el = ref<HTMLDivElement>()
|
||||
let editor: monaco.editor.IStandaloneDiffEditor | null = null
|
||||
const leftEl = ref<HTMLDivElement>()
|
||||
const rightEl = ref<HTMLDivElement>()
|
||||
let left: monaco.editor.IStandaloneCodeEditor | null = null
|
||||
let right: monaco.editor.IStandaloneCodeEditor | null = null
|
||||
|
||||
const OPTIONS: monaco.editor.IStandaloneEditorConstructionOptions = {
|
||||
theme: 'sanguo-dark',
|
||||
readOnly: true,
|
||||
fontSize: 12,
|
||||
minimap: { enabled: false },
|
||||
scrollBeyondLastLine: false,
|
||||
automaticLayout: true,
|
||||
lineNumbersMinChars: 4,
|
||||
scrollbar: { alwaysConsumeMouseWheel: false },
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!el.value) return
|
||||
monaco.editor.defineTheme('sanguo-dark', {
|
||||
base: 'vs-dark',
|
||||
inherit: true,
|
||||
@@ -40,45 +53,57 @@ onMounted(() => {
|
||||
'editorLineNumber.foreground': '#3a4654',
|
||||
'editorLineNumber.activeForeground': '#00e5ff',
|
||||
'editor.lineHighlightBackground': '#0a1018',
|
||||
'diffEditor.insertedTextBackground': '#12291c',
|
||||
'diffEditor.removedTextBackground': '#2a1418',
|
||||
},
|
||||
})
|
||||
editor = monaco.editor.createDiffEditor(el.value, {
|
||||
theme: 'sanguo-dark',
|
||||
readOnly: true,
|
||||
renderSideBySide: true,
|
||||
fontSize: 12,
|
||||
minimap: { enabled: false },
|
||||
scrollBeyondLastLine: false,
|
||||
automaticLayout: true,
|
||||
if (leftEl.value) left = monaco.editor.create(leftEl.value, { ...OPTIONS, value: props.original, language: props.language })
|
||||
if (rightEl.value) right = monaco.editor.create(rightEl.value, { ...OPTIONS, value: props.modified, language: props.language })
|
||||
// 左右滚动联动:任一侧滚动时同步另一侧
|
||||
left?.onDidScrollChange(() => {
|
||||
if (right && left) {
|
||||
right.setScrollTop(left.getScrollTop())
|
||||
right.setScrollLeft(left.getScrollLeft())
|
||||
}
|
||||
})
|
||||
right?.onDidScrollChange(() => {
|
||||
if (left && right) {
|
||||
left.setScrollTop(right.getScrollTop())
|
||||
left.setScrollLeft(right.getScrollLeft())
|
||||
}
|
||||
})
|
||||
setModels()
|
||||
})
|
||||
|
||||
function setModels(): void {
|
||||
if (!editor) return
|
||||
editor.setModel({
|
||||
original: monaco.editor.createModel(props.original, props.language),
|
||||
modified: monaco.editor.createModel(props.modified, props.language),
|
||||
})
|
||||
}
|
||||
|
||||
watch(() => [props.original, props.modified], setModels)
|
||||
watch(() => props.original, (v) => left?.setValue(v))
|
||||
watch(() => props.modified, (v) => right?.setValue(v))
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
const m = editor?.getModel()
|
||||
m?.original?.dispose()
|
||||
m?.modified?.dispose()
|
||||
editor?.dispose()
|
||||
editor = null
|
||||
left?.dispose()
|
||||
right?.dispose()
|
||||
left = null
|
||||
right = null
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="el" class="diff-editor"></div>
|
||||
<div class="diff-wrap" data-relayout="v3">
|
||||
<div class="pane">
|
||||
<div class="pane-tag mono">快照版本</div>
|
||||
<div ref="leftEl" class="pane-editor"></div>
|
||||
</div>
|
||||
<div class="pane">
|
||||
<div class="pane-tag mono pane-cur">当前代码</div>
|
||||
<div ref="rightEl" class="pane-editor"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.diff-editor { height: 100%; min-height: 300px; }
|
||||
.diff-wrap { display: flex; height: 100%; min-height: 300px; gap: 0; background: #05080d; }
|
||||
.pane { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; border-right: 1px solid #16202e; }
|
||||
.pane:last-child { border-right: none; }
|
||||
.pane-tag {
|
||||
font-size: 10px; color: #64798a; padding: 3px 10px; letter-spacing: 1px;
|
||||
border-bottom: 1px solid #16202e; background: #0a0f17;
|
||||
}
|
||||
.pane-cur { color: #00e5ff; }
|
||||
.pane-editor { flex: 1; min-height: 0; }
|
||||
</style>
|
||||
|
||||
@@ -139,6 +139,7 @@ function runBacktest(): void {
|
||||
const versions = ref<CodeVersion[]>([])
|
||||
const versionsOpen = ref(false)
|
||||
const diffCode = ref<string | null>(null)
|
||||
const diffReady = ref(false)
|
||||
const versionsLoading = ref(false)
|
||||
|
||||
async function openVersions(): Promise<void> {
|
||||
@@ -146,6 +147,7 @@ async function openVersions(): Promise<void> {
|
||||
versionsOpen.value = true
|
||||
versionsLoading.value = true
|
||||
diffCode.value = null
|
||||
diffReady.value = false
|
||||
try {
|
||||
versions.value = await getCodeVersions(active.value.name)
|
||||
} catch {
|
||||
@@ -157,8 +159,12 @@ async function openVersions(): Promise<void> {
|
||||
|
||||
async function showDiff(h8: string): Promise<void> {
|
||||
if (!active.value) return
|
||||
diffReady.value = false
|
||||
try {
|
||||
diffCode.value = await getCodeVersion(active.value.name, h8)
|
||||
// 抽屉展开动画(~300ms)期间容器宽为 0,Monaco diff 在其中创建会把左右分栏算死
|
||||
// (左栏被压扁且事后 layout() 救不回)。等动画结束容器全宽后再挂载组件。
|
||||
setTimeout(() => { diffReady.value = true }, 360)
|
||||
} catch {
|
||||
ElMessage.error('读取版本失败')
|
||||
}
|
||||
@@ -245,8 +251,8 @@ async function showDiff(h8: string): Promise<void> {
|
||||
<span class="muted mono" style="font-size:11px">{{ (v.size / 1024).toFixed(1) }} KB</span>
|
||||
<button class="term-btn sm" style="margin-left:auto" @click="showDiff(v.code_version)">对比当前</button>
|
||||
</div>
|
||||
<div v-if="diffCode != null" class="ver-diff">
|
||||
<div class="muted mono" style="font-size:11px;margin-bottom:6px">左=快照版本 · 右=当前代码</div>
|
||||
<div v-if="diffCode != null && diffReady" class="ver-diff">
|
||||
<div class="muted mono" style="font-size:11px;margin-bottom:6px">左右滚动联动 · 快照 vs 当前</div>
|
||||
<MonacoDiff :original="diffCode" :modified="code" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user