数据结构优化
This commit is contained in:
@@ -24,7 +24,7 @@
|
||||
<Footer v-if="!isAdminOrLogin" />
|
||||
|
||||
<!-- Snippet Modal (Hide on Admin & Login) -->
|
||||
<SnippetModal v-if="!isAdminOrLogin" />
|
||||
<!-- SnippetModal is managed by Snippets.vue page, not here -->
|
||||
|
||||
<!-- Inquiry Modal (Hide on Admin & Login) -->
|
||||
<InquiryModal v-if="!isAdminOrLogin" />
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<div class="flex items-center gap-4">
|
||||
<CustomSelect
|
||||
v-model="selectedLanguage"
|
||||
:options="languageOptions.filter(opt => !opt.disabled)"
|
||||
:options="languageOptions"
|
||||
@update:modelValue="handleLanguageChange"
|
||||
placeholder="选择语言"
|
||||
style="width: 180px; font-family: monospace; font-size: 0.75rem;"
|
||||
@@ -449,13 +449,15 @@ const getConsoleTemplate = (jsCode: string) => {
|
||||
`
|
||||
}
|
||||
|
||||
let runTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const handleCodeChange = () => {
|
||||
highlightCode()
|
||||
// 对于非 Web 语言(如 Python/React),不自动运行,等待用户点击 Run
|
||||
if (['html', 'css', 'javascript'].includes(selectedLanguage.value)) {
|
||||
// Debounce auto-run for lightweight languages
|
||||
clearTimeout(window.runTimer)
|
||||
window.runTimer = setTimeout(() => runCode(), 1000)
|
||||
if (runTimer) clearTimeout(runTimer)
|
||||
runTimer = setTimeout(() => runCode(), 1000)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<template>
|
||||
<footer class="py-8 text-center border-t border-white/5 relative z-10">
|
||||
<div class="flex justify-center items-center gap-4 mb-4">
|
||||
<a @click="window.open('admin.html', '_blank')" class="text-xs text-art-muted/30 hover:text-art-accent cursor-pointer">管理入口</a>
|
||||
<a @click="openAdmin" class="text-xs text-art-muted/30 hover:text-art-accent cursor-pointer">管理入口</a>
|
||||
</div>
|
||||
<p class="text-art-muted text-xs font-mono tracking-widest opacity-50">© 2024 年糕崽崽. 保留所有权利.</p>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Footer组件的逻辑可以在这里添加
|
||||
const openAdmin = () => {
|
||||
window.open('admin.html', '_blank')
|
||||
}
|
||||
</script>
|
||||
@@ -6,7 +6,7 @@
|
||||
<a @click="navigate('/works')" class="font-serif text-3xl italic text-white hover:text-art-accent cursor-pointer">作品</a>
|
||||
<a @click="navigate('/snippets')" class="font-serif text-3xl italic text-white hover:text-art-accent cursor-pointer">代码</a>
|
||||
<a @click="navigate('/about')" class="font-serif text-3xl italic text-white hover:text-art-accent cursor-pointer">关于</a>
|
||||
<a @click="window.open('admin.html', '_blank')" class="font-mono text-sm text-art-muted mt-8">管理入口</a>
|
||||
<a @click="openAdmin" class="font-mono text-sm text-art-muted mt-8">管理入口</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -30,6 +30,10 @@ const navigate = (target: string) => {
|
||||
toggleMobileMenu()
|
||||
}
|
||||
|
||||
const openAdmin = () => {
|
||||
window.open('admin.html', '_blank')
|
||||
}
|
||||
|
||||
const refreshIcons = () => {
|
||||
if ((window as any).lucide) {
|
||||
(window as any).lucide.createIcons()
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted, computed, nextTick } from 'vue'
|
||||
import { ref, watch, computed, nextTick } from 'vue'
|
||||
import hljs from 'highlight.js'
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -90,7 +90,6 @@ const emit = defineEmits(['close'])
|
||||
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(() => {
|
||||
|
||||
@@ -178,7 +178,7 @@ const closeDropdown = (e: MouseEvent) => {
|
||||
}
|
||||
|
||||
const handleChangePassword = () => {
|
||||
toast.showToast('功能开发中...', 'info')
|
||||
toast.showToast('功能开发中...', 'success')
|
||||
isUserDropdownOpen.value = false
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export const useInteractions = () => {
|
||||
const initTiltEffect = () => {
|
||||
const tiltCards = document.querySelectorAll('.tilt-card')
|
||||
tiltCards.forEach(card => {
|
||||
card.addEventListener('mousemove', (e) => {
|
||||
card.addEventListener('mousemove', (e: MouseEvent) => {
|
||||
const cardRect = card.getBoundingClientRect()
|
||||
const x = e.clientX - cardRect.left
|
||||
const y = e.clientY - cardRect.top
|
||||
@@ -25,8 +25,9 @@ export const useInteractions = () => {
|
||||
const xPercent = (x / cardRect.width) * 100
|
||||
const yPercent = (y / cardRect.height) * 100
|
||||
|
||||
card.style.setProperty('--mouse-x', `${xPercent}%`)
|
||||
card.style.setProperty('--mouse-y', `${yPercent}%`)
|
||||
const htmlCard = card as HTMLElement
|
||||
htmlCard.style.setProperty('--mouse-x', `${xPercent}%`)
|
||||
htmlCard.style.setProperty('--mouse-y', `${yPercent}%`)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -17,16 +17,17 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 描述字段 -->
|
||||
<!-- Slug 字段 -->
|
||||
<div class="form-group">
|
||||
<label for="description" class="form-label">描述</label>
|
||||
<textarea
|
||||
id="description"
|
||||
v-model="tagForm.description"
|
||||
<label for="slug" class="form-label">别名 (Slug)</label>
|
||||
<input
|
||||
type="text"
|
||||
id="slug"
|
||||
v-model="tagForm.slug"
|
||||
class="form-input"
|
||||
placeholder="请输入标签描述"
|
||||
rows="3"
|
||||
></textarea>
|
||||
placeholder="请输入标签别名(用于URL,如:vue-3)"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 表单按钮 -->
|
||||
@@ -59,7 +60,7 @@ const isEdit = computed(() => !!route.params.id)
|
||||
// 标签表单数据
|
||||
const tagForm = ref({
|
||||
name: '',
|
||||
description: ''
|
||||
slug: ''
|
||||
})
|
||||
|
||||
// 获取标签详情
|
||||
@@ -71,7 +72,7 @@ const fetchTagDetail = async () => {
|
||||
const tag = await adminGetTag(tagId)
|
||||
tagForm.value = {
|
||||
name: tag.name,
|
||||
description: tag.description
|
||||
slug: tag.slug
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('Failed to fetch tag detail:', error)
|
||||
|
||||
1
client/src/types/global.d.ts
vendored
1
client/src/types/global.d.ts
vendored
@@ -6,4 +6,5 @@ declare interface Window {
|
||||
closeSnippet?: () => void
|
||||
openInquiry?: () => void
|
||||
closeInquiry?: () => void
|
||||
open?: (url?: string, target?: string, features?: string) => Window | null
|
||||
}
|
||||
Reference in New Issue
Block a user