6 changed files with 202 additions and 227 deletions
-
BINsrc/assets/image.png
-
6src/assets/index.ts
-
104src/components/blogs/HomePage.vue
-
210src/components/blogs/ceshi.vue
-
41src/views/blog/blogcontent/BlogDetailView.vue
-
68src/views/blog/blogcontent/BlogListView.vue
After Width: 62 | Height: 67 | Size: 11 KiB |
@ -1,189 +1,45 @@ |
|||
<template> |
|||
<div> |
|||
<div |
|||
v-for="anchor in titles" |
|||
:style="{ padding: `10px 0 10px ${anchor.indent}px` }" |
|||
@click="handleAnchorClick(anchor)" |
|||
:key="anchor.lineIndex" |
|||
> |
|||
<a style="cursor: pointer">{{ anchor.title }}</a> |
|||
|
|||
<div v-for="blog in bloglist" :key="blog.id"> |
|||
<!-- 在这里展示你的博客内容 --> |
|||
<h2>{{ blog.blogtitle }}</h2> |
|||
<p>{{ blog.blogcontent }}</p> |
|||
</div> |
|||
<v-md-preview :text="text" ref="preview" /> |
|||
<a-pagination v-model:current="current" v-if="dataLoaded" :total="total" :page-size="pageSize" @change="onPageChange" |
|||
show-less-items /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
<script lang="ts" setup> |
|||
import { ref, onMounted } from 'vue'; |
|||
|
|||
const text = ` |
|||
# heading 1 |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
|
|||
## heading 2 |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
|
|||
### heading 3 |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontentcontentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
contentcontentcontent |
|||
|
|||
|
|||
`; |
|||
|
|||
const preview = ref<any>(null); |
|||
const titles = ref<{ title: string; lineIndex: string; indent: number }[]>([]); |
|||
|
|||
onMounted(() => { |
|||
const anchors = document.querySelectorAll('h1, h2, h3, h4, h5, h6'); |
|||
const titlesArray = Array.from(anchors).filter((title) => !!title.innerText.trim()); |
|||
|
|||
if (!titlesArray.length) { |
|||
titles.value = []; |
|||
return; |
|||
import type { blogInterface } from '@/api/admin'; |
|||
import { get } from '@/tools/request'; |
|||
const current = ref(1); |
|||
const total = ref(); |
|||
const pageSize = ref(5); |
|||
const bloglist = ref<blogInterface[]>([]) |
|||
const dataLoaded = ref(false); |
|||
|
|||
const fetchData = async (page: number, pageSize: number) => { |
|||
try { |
|||
const response = await get('/blogs/list', { |
|||
page, |
|||
page_size: pageSize, |
|||
}); |
|||
bloglist.value = response.data.data.blogs; |
|||
total.value = response.data.data.total; |
|||
} catch (error) { |
|||
console.error('Failed to fetch data', error); |
|||
} |
|||
}; |
|||
|
|||
const hTags = Array.from(new Set(titlesArray.map((title) => title.tagName))).sort(); |
|||
const onPageChange = (page: number) => { |
|||
current.value = page; |
|||
fetchData(page, pageSize.value); |
|||
}; |
|||
|
|||
titles.value = titlesArray.map((el) => ({ |
|||
title: el.innerText, |
|||
lineIndex: el.getAttribute('data-v-md-line') || '', // 确认属性名是否正确 |
|||
indent: 20 * (parseInt(el.tagName.substring(1)) - 1) // 确认缩进计算是否正确 |
|||
})); |
|||
onMounted(() => { |
|||
fetchData(current.value, pageSize.value); |
|||
}); |
|||
|
|||
function handleAnchorClick(anchor: { title: string; lineIndex: string }) { |
|||
if (preview.value) { |
|||
const heading = preview.value.$el.querySelector(`[data-v-md-line="${anchor.lineIndex}"]`); |
|||
|
|||
if (heading) { |
|||
preview.value.scrollToTarget({ |
|||
target: heading, |
|||
scrollContainer: window, |
|||
top: 60, |
|||
}); |
|||
} else { |
|||
console.error(`Heading element not found for lineIndex: ${anchor.lineIndex}`); |
|||
} |
|||
} else { |
|||
console.error('Preview component not initialized.'); |
|||
} |
|||
} |
|||
</script> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue