mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-06 18:36:55 +08:00
- Updated `getShowContentParts` function to handle message content more robustly, ensuring proper display of content parts. - Refactored `GamepadViewer.vue` to use async component loading for `GamepadDisplay`, added a toggle for real-time preview. - Implemented debounced search functionality in `PointGoodsView.vue` for improved performance during keyword searches. - Enhanced `PointOrderView.vue` with order filtering capabilities and added statistics display for better user insights. - Improved `PointUserHistoryView.vue` by adding export functionality for history data and enhanced filtering options. - Updated `PointUserLayout.vue` to improve card styling and tab navigation experience. - Refined `PointUserSettings.vue` layout for better user interaction and added responsive design adjustments. - Adjusted `vite.config.mts` for better dependency management and build optimization.
122 lines
3.5 KiB
Vue
122 lines
3.5 KiB
Vue
<script setup lang="ts">
|
||
import { onMounted, onBeforeUnmount, ref, watch } from 'vue'
|
||
import * as monaco from 'monaco-editor'
|
||
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
|
||
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
|
||
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
|
||
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
|
||
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
|
||
|
||
|
||
const { language, height = 400, theme = 'vs-dark', options, path } = defineProps<{
|
||
language: string
|
||
height?: number
|
||
theme?: string
|
||
options?: Record<string, any>
|
||
path?: string
|
||
}>()
|
||
|
||
const value = defineModel<string>('value')
|
||
|
||
// 在创建编辑器前确保容器存在
|
||
const ready = ref(false)
|
||
const initError = ref<string | null>(null)
|
||
const containerRef = ref<HTMLElement | null>(null)
|
||
let editor: monaco.editor.IStandaloneCodeEditor | null = null
|
||
let model: monaco.editor.ITextModel | null = null
|
||
let createdModel = false
|
||
|
||
// 配置 Monaco Environment
|
||
;(self as any).MonacoEnvironment = {
|
||
getWorker(_: string, label: string) {
|
||
if (label === 'json') {
|
||
return new jsonWorker()
|
||
}
|
||
if (label === 'css' || label === 'scss' || label === 'less') {
|
||
return new cssWorker()
|
||
}
|
||
if (label === 'html' || label === 'handlebars' || label === 'razor') {
|
||
return new htmlWorker()
|
||
}
|
||
if (label === 'typescript' || label === 'javascript') {
|
||
return new tsWorker()
|
||
}
|
||
return new editorWorker()
|
||
},
|
||
}
|
||
|
||
onMounted(async () => {
|
||
try {
|
||
const uri = monaco.Uri.parse(
|
||
path ?? `inmemory://model/${crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2)}.${language ?? 'txt'}`,
|
||
)
|
||
model = monaco.editor.getModel(uri)
|
||
if (!model) {
|
||
model = monaco.editor.createModel(value?.value ?? '', language, uri)
|
||
createdModel = true
|
||
}
|
||
|
||
editor = monaco.editor.create(containerRef.value!, {
|
||
model,
|
||
theme,
|
||
automaticLayout: true,
|
||
...(options ?? {}),
|
||
})
|
||
|
||
// 同步 model -> v-model
|
||
editor.onDidChangeModelContent(() => {
|
||
const current = model!.getValue()
|
||
if (current !== value.value) value.value = current
|
||
})
|
||
|
||
ready.value = true
|
||
} catch (err) {
|
||
console.error('Monaco 初始化失败:', err)
|
||
initError.value = (err as Error)?.message ?? String(err)
|
||
}
|
||
})
|
||
|
||
// v-model 变更 -> model
|
||
watch(value, (nv) => {
|
||
if (model && typeof nv === 'string' && nv !== model.getValue()) {
|
||
model.setValue(nv)
|
||
}
|
||
})
|
||
|
||
// 语言切换
|
||
watch(() => language, (lang) => {
|
||
if (model && lang) {
|
||
monaco.editor.setModelLanguage(model, lang)
|
||
}
|
||
})
|
||
|
||
// 主题切换
|
||
watch(() => theme, (t) => {
|
||
if (editor && t) {
|
||
editor.updateOptions({ theme: t })
|
||
}
|
||
})
|
||
|
||
onBeforeUnmount(() => {
|
||
try {
|
||
editor?.dispose()
|
||
// 仅销毁我们创建的临时 model,避免复用路径时把共享 model 误删
|
||
if (createdModel && model) {
|
||
model.dispose()
|
||
}
|
||
} catch {}
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<div :style="`height: ${height}px; width: 100%; position: relative;`">
|
||
<div v-if="!ready" :style="`position:absolute; inset:0; display:flex; align-items:center; justify-content:center; color: var(--text-color, #888); text-align:center; padding:8px;`">
|
||
<div>
|
||
<div>正在加载编辑器…</div>
|
||
<div v-if="initError" style="margin-top:6px; color:#d9534f; font-size:12px;">{{ initError }}</div>
|
||
</div>
|
||
</div>
|
||
<div ref="containerRef" :style="`height: ${height}px; width: 100%;`"></div>
|
||
</div>
|
||
</template>
|