初始化
This commit is contained in:
33
client/src/components/CodeBlock.vue
Normal file
33
client/src/components/CodeBlock.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<code ref="codeBlock" :class="languageClass">{{ code }}</code>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch, nextTick } from 'vue'
|
||||
import hljs from 'highlight.js'
|
||||
|
||||
const props = defineProps<{
|
||||
code: string
|
||||
language: string
|
||||
}>()
|
||||
|
||||
const codeBlock = ref<HTMLElement | null>(null)
|
||||
|
||||
const languageClass = `language-${props.language || 'plaintext'}`
|
||||
|
||||
const highlight = () => {
|
||||
if (codeBlock.value) {
|
||||
// Reset internal state if needed, though highlighting overwrites innerHTML
|
||||
delete codeBlock.value.dataset.highlighted
|
||||
hljs.highlightElement(codeBlock.value)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
highlight()
|
||||
})
|
||||
|
||||
watch(() => props.code, () => {
|
||||
nextTick(highlight)
|
||||
})
|
||||
</script>
|
||||
@@ -1,11 +1,12 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="isOpen"
|
||||
class="fixed inset-0 z-[100] bg-black/90 backdrop-blur-sm flex items-center justify-center p-4 md:p-10 transition-opacity duration-300"
|
||||
class="fixed inset-0 z-[100] flex items-center justify-center p-4 md:p-10 transition-opacity duration-300 pointer-events-auto"
|
||||
:class="{ 'opacity-0': isAnimating, 'opacity-100': !isAnimating }"
|
||||
>
|
||||
<div class="absolute inset-0 bg-black/90 backdrop-blur-sm" @click="close"></div>
|
||||
<div
|
||||
class="bg-[#0a0a0c] border border-white/10 w-full max-w-6xl h-full md:h-[80vh] rounded-2xl flex flex-col overflow-hidden shadow-2xl transform transition-transform duration-300"
|
||||
class="relative z-[101] bg-[#0a0a0c] border border-white/10 w-full max-w-6xl h-[80vh] rounded-2xl flex flex-col overflow-hidden shadow-2xl transform transition-transform duration-300"
|
||||
:class="{ 'scale-95': isAnimating, 'scale-100': !isAnimating }"
|
||||
>
|
||||
<!-- Header -->
|
||||
@@ -23,10 +24,10 @@
|
||||
<div class="flex-1 flex flex-col md:flex-row h-full overflow-hidden">
|
||||
<!-- Code Section -->
|
||||
<div class="w-full md:w-1/2 bg-[#0d0d0d] overflow-auto p-6 border-r border-white/10 relative group">
|
||||
<button class="absolute top-4 right-4 text-xs bg-white/10 px-2 py-1 rounded text-white/50 hover:text-white" @click="copyCode">
|
||||
<button class="absolute top-4 right-4 text-xs bg-white/10 px-2 py-1 rounded text-white/50 hover:text-white z-10" @click="copyCode">
|
||||
复制
|
||||
</button>
|
||||
<pre class="font-mono text-sm leading-relaxed text-gray-300">{{ code }}</pre>
|
||||
<pre class="font-mono text-sm leading-relaxed"><code ref="codeBlock" :class="languageClass">{{ code }}</code></pre>
|
||||
</div>
|
||||
|
||||
<!-- Preview Section -->
|
||||
@@ -72,7 +73,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted, computed } from 'vue'
|
||||
import { ref, watch, onMounted, computed, nextTick } from 'vue'
|
||||
import hljs from 'highlight.js'
|
||||
|
||||
const props = defineProps<{
|
||||
isOpen: boolean
|
||||
@@ -87,6 +89,24 @@ const isAnimating = ref(true)
|
||||
const mouseX = ref(0)
|
||||
const mouseY = ref(0)
|
||||
const containerRect = ref<DOMRect | null>(null)
|
||||
const codeBlock = ref<HTMLElement | null>(null)
|
||||
|
||||
const languageClass = computed(() => {
|
||||
const map: Record<string, string> = {
|
||||
'mouse': 'javascript',
|
||||
'glass': 'css',
|
||||
'noise': 'xml',
|
||||
'animate': 'css'
|
||||
}
|
||||
return `language-${map[props.type] || 'plaintext'}`
|
||||
})
|
||||
|
||||
const highlightCode = () => {
|
||||
if (codeBlock.value) {
|
||||
delete codeBlock.value.dataset.highlighted
|
||||
hljs.highlightElement(codeBlock.value)
|
||||
}
|
||||
}
|
||||
|
||||
// Watch isOpen to handle entry/exit animations
|
||||
watch(() => props.isOpen, (newVal) => {
|
||||
@@ -101,6 +121,11 @@ watch(() => props.isOpen, (newVal) => {
|
||||
setTimeout(() => {
|
||||
if (window.lucide) window.lucide.createIcons()
|
||||
}, 50)
|
||||
|
||||
// Highlight code
|
||||
nextTick(() => {
|
||||
highlightCode()
|
||||
})
|
||||
} else {
|
||||
document.body.style.overflow = ''
|
||||
isAnimating.value = true
|
||||
|
||||
Reference in New Issue
Block a user