diff --git a/packages/blog/app/components/AppSearchBox.vue b/packages/blog/app/components/AppSearchBox.vue new file mode 100644 index 0000000..9a06bab --- /dev/null +++ b/packages/blog/app/components/AppSearchBox.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/packages/blog/app/composables/useDebounce.ts b/packages/blog/app/composables/useDebounce.ts new file mode 100644 index 0000000..e755b27 --- /dev/null +++ b/packages/blog/app/composables/useDebounce.ts @@ -0,0 +1,7 @@ +export function useDebounce void>(fn: T, delay = 300): T { + let timer: ReturnType | null = null + return ((...args: Parameters) => { + if (timer) clearTimeout(timer) + timer = setTimeout(() => fn(...args), delay) + }) as T +} diff --git a/packages/blog/app/composables/useDeviceInfoCard.ts b/packages/blog/app/composables/useDeviceInfoCard.ts index bc5582f..3fd77b0 100644 --- a/packages/blog/app/composables/useDeviceInfoCard.ts +++ b/packages/blog/app/composables/useDeviceInfoCard.ts @@ -86,7 +86,7 @@ export function useDeviceInfo() { onMounted(() => { document.addEventListener('contextmenu', onContext) - document.addEventListener('touchstart', onTouchStart, { passive: false }) + document.addEventListener('touchstart', onTouchStart, { passive: true }) document.addEventListener('touchmove', onTouchMove, { passive: true }) document.addEventListener('touchend', onTouchEnd) }) diff --git a/packages/blog/app/pages/blog/[slug].vue b/packages/blog/app/pages/blog/[slug].vue index a180071..2926059 100644 --- a/packages/blog/app/pages/blog/[slug].vue +++ b/packages/blog/app/pages/blog/[slug].vue @@ -283,129 +283,124 @@ useSeoMeta({ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); /* Markdown 内容样式 */ - :deep { - h1, - h2, - h3, - h4, - h5, - h6 { - margin-top: 2rem; - margin-bottom: 1rem; - color: var(--text); - font-weight: 600; - position: relative; - padding-bottom: 0.5rem; - - &::after { - content: ''; - position: absolute; - bottom: 0; - left: 0; - width: 60px; - height: 3px; - background: var(--primary); - border-radius: 2px; - } - } - - h1 { - font-size: 2rem; - } - h2 { - font-size: 1.75rem; - } - h3 { - font-size: 1.5rem; - } - h4 { - font-size: 1.25rem; - } - - p { - margin-bottom: 1.5rem; - font-size: 1.05rem; + :deep(h1), + :deep(h2), + :deep(h3), + :deep(h4), + :deep(h5), + :deep(h6) { + margin-top: 2rem; + margin-bottom: 1rem; + color: var(--text); + font-weight: 600; + position: relative; + padding-bottom: 0.5rem; + + &::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 60px; + height: 3px; + background: var(--primary); + border-radius: 2px; } + } - ul, - ol { - padding-left: 1.5rem; - margin-bottom: 1.5rem; - - li { - margin-bottom: 0.5rem; + /* 单独字号 */ + :deep(h1) { + font-size: 2rem; + } + :deep(h2) { + font-size: 1.75rem; + } + :deep(h3) { + font-size: 1.5rem; + } + :deep(h4) { + font-size: 1.25rem; + } - &::marker { - color: var(--primary); - } - } - } + /* 其余元素同样写法 */ + :deep(p) { + margin-bottom: 1.5rem; + font-size: 1.05rem; + } - a { - color: var(--primary); - text-decoration: none; - border-bottom: 1px solid transparent; - transition: all 0.3s ease; + :deep(ul), + :deep(ol) { + padding-left: 1.5rem; + margin-bottom: 1.5rem; - &:hover { - border-bottom-color: var(--primary); + li { + margin-bottom: 0.5rem; + &::marker { + color: var(--primary); } } + } - img { - max-width: 100%; - border-radius: 12px; - margin: 2rem 0; - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); - } - - pre { - background: rgba(var(--text), 0.05); - border-radius: 12px; - padding: 1.5rem; - margin: 1.5rem 0; - overflow-x: auto; - border: 1px solid var(--card-border); - - code { - background: transparent; - padding: 0; - border-radius: 0; - } + :deep(a) { + color: var(--primary); + text-decoration: none; + border-bottom: 1px solid transparent; + transition: all 0.3s ease; + &:hover { + border-bottom-color: var(--primary); } + } - code:not(pre code) { - background: rgba(var(--primary), 0.1); - color: var(--primary); - padding: 0.2rem 0.4rem; - border-radius: 4px; - font-size: 0.9em; - } + :deep(img) { + max-width: 100%; + border-radius: 12px; + margin: 2rem 0; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); + } - blockquote { - border-left: 4px solid var(--primary); - margin: 1.5rem 0; - padding: 0.5rem 0 0.5rem 1.5rem; - background: rgba(var(--primary), 0.05); - border-radius: 0 8px 8px 0; - font-style: italic; + :deep(pre) { + background: rgba(var(--text), 0.05); + border-radius: 12px; + padding: 1.5rem; + margin: 1.5rem 0; + overflow-x: auto; + border: 1px solid var(--card-border); + code { + background: transparent; + padding: 0; + border-radius: 0; } + } - table { - width: 100%; - border-collapse: collapse; - margin: 1.5rem 0; + :deep(code:not(pre code)) { + background: rgba(var(--primary), 0.1); + color: var(--primary); + padding: 0.2rem 0.4rem; + border-radius: 4px; + font-size: 0.9em; + } - th, - td { - padding: 0.75rem; - border: 1px solid var(--card-border); - } + :deep(blockquote) { + border-left: 4px solid var(--primary); + margin: 1.5rem 0; + padding: 0.5rem 0 0.5rem 1.5rem; + background: rgba(var(--primary), 0.05); + border-radius: 0 8px 8px 0; + font-style: italic; + } - th { - background: rgba(var(--primary), 0.1); - font-weight: 600; - } + :deep(table) { + width: 100%; + border-collapse: collapse; + margin: 1.5rem 0; + th, + td { + padding: 0.75rem; + border: 1px solid var(--card-border); + } + th { + background: rgba(var(--primary), 0.1); + font-weight: 600; } } } @@ -458,16 +453,14 @@ useSeoMeta({ .post-content { padding: 1.5rem; - :deep { - h1 { - font-size: 1.75rem; - } - h2 { - font-size: 1.5rem; - } - h3 { - font-size: 1.25rem; - } + :deep(h1) { + font-size: 1.75rem; + } + :deep(h2) { + font-size: 1.5rem; + } + :deep(h3) { + font-size: 1.25rem; } } } diff --git a/packages/blog/app/pages/blog/index.vue b/packages/blog/app/pages/blog/index.vue index 4e3fd8d..38ca796 100644 --- a/packages/blog/app/pages/blog/index.vue +++ b/packages/blog/app/pages/blog/index.vue @@ -1,21 +1,42 @@