Browse Source

add new

master
panda 8 months ago
parent
commit
65a1cef200
  1. BIN
      src/assets/image.png
  2. 6
      src/assets/index.ts
  3. 98
      src/components/blogs/HomePage.vue
  4. 210
      src/components/blogs/ceshi.vue
  5. 27
      src/views/blog/blogcontent/BlogDetailView.vue
  6. 68
      src/views/blog/blogcontent/BlogListView.vue

BIN
src/assets/image.png

After

Width: 62  |  Height: 67  |  Size: 11 KiB

6
src/assets/index.ts

@ -3,7 +3,7 @@ import { createFromIconfontCN } from '@ant-design/icons-vue';
function createIconComponent(iconType: string) { function createIconComponent(iconType: string) {
const IconComponent = createFromIconfontCN({ const IconComponent = createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/c/font_4513281_qhbaqfo6egj.js', // 在 iconfont.cn 上生成 scriptUrl: '//at.alicdn.com/t/c/font_4513281_1cb6b9dny0i.js', // 在 iconfont.cn 上生成
}); });
return defineComponent({ return defineComponent({
@ -32,6 +32,10 @@ const iconComponents = {
YanJingLined: createIconComponent('icon-yanjing'), YanJingLined: createIconComponent('icon-yanjing'),
XieZiLined: createIconComponent('icon-xiezi'), XieZiLined: createIconComponent('icon-xiezi'),
CravatarLined: createIconComponent('icon-cravatar'), CravatarLined: createIconComponent('icon-cravatar'),
GongAnLined: createIconComponent('icon-gonganbeian'),
IcpLined: createIconComponent('icon-wsmp-icprecord'),
BanQuanLined: createIconComponent('icon-banquan'),
} }

98
src/components/blogs/HomePage.vue

@ -104,6 +104,54 @@
</div> </div>
</div> </div>
<div class="footer">
<div class="miit">
<a-space wrap>
<a-text>
<component :is=iconComponents.BanQuanLined />
<span>Copyright © 2024</span>
</a-text>
<a-button type="link" href="/home">
<component :is=iconComponents.TitleOutLined />
<span>SunFree</span>
</a-button>
<a-button type="link" href="https://beian.miit.gov.cn/">
<component :is=iconComponents.IcpLined />
<span>苏ICP备2024067473号-1</span>
</a-button>
<a-button type="link" href="https://beian.mps.gov.cn/#/query/webSearch">
<component :is=iconComponents.GongAnLined />
<span>苏公网安备32021402003003号</span>
</a-button>
</a-space>
</div>
<div class="badge">
<a-space wrap>
<a-button type="link" class="badge-button" href="https://cn.vuejs.org/">
<span class="tag-nav">front-end</span>
<span class="tag-main-first">Vue.js</span>
</a-button>
<a-button type="link" class="badge-button" href="https://fastapi.tiangolo.com/zh/">
<span class="tag-nav">back-end</span>
<span class="tag-main-second">FastAPI</span>
</a-button>
<a-button type="link" class="badge-button" href="https://www.antdv.com/docs/vue/introduce-cn/">
<span class="tag-nav">UI</span>
<span class="tag-main-third">Ant Design Vue</span>
</a-button>
<a-button type="link" class="badge-button" href="https://cloud.tencent.com/">
<span class="tag-nav">VPS</span>
<span class="tag-main-fourth">tencent cloud</span>
</a-button>
</a-space>
</div>
<div>
</div>
<div></div>
</div>
</Simplebar> </Simplebar>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -121,7 +169,6 @@ import { useRouter, useRoute } from 'vue-router';
import iconComponents from "@/assets/index"; import iconComponents from "@/assets/index";
import type { classticInterface } from '@/api/admin'; import type { classticInterface } from '@/api/admin';
import type { comLinkInterface } from '@/api/admin/index'; import type { comLinkInterface } from '@/api/admin/index';
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const author = ref("SunFree.") const author = ref("SunFree.")
@ -203,13 +250,13 @@ const items = ref<MenuProps['items']>([
}, },
]); ]);
const jumpMenu = ({ key }:{key:string}) => { const jumpMenu = ({ key }: { key: string }) => {
// `item` `key` `url` // `item` `key` `url`
const selectedItem = items.value.find((i:any) => i.key === key); const selectedItem = items.value.find((i: any) => i.key === key);
if (selectedItem && selectedItem.url) { if (selectedItem && selectedItem.url) {
router.push(selectedItem.url); router.push(selectedItem.url);
} }
}; };
const updateCarouselVisibility = (routeName: any) => { const updateCarouselVisibility = (routeName: any) => {
handleScrollEnabled.value = false; handleScrollEnabled.value = false;
if (scrollbar.value) { if (scrollbar.value) {
@ -684,4 +731,47 @@ watch(
.statistic { .statistic {
text-align: center; text-align: center;
} }
.footer {
display: flex;
flex-direction: column;
align-items: center;
}
.footer a {
color: #6e5555;
}
.footer .badge {
margin: 48px 0;
}
.footer .miit {
margin: 48px 0 0 0;
}
.footer .badge .tag-nav {
background-color: #505050;
}
.footer .miit span{
padding: 0 6px;
}
.footer .badge span {
padding: 0 6px;
color: white;
}
.footer .badge .tag-main-first {
background-color: rgb(3, 3, 250);
}
.footer .badge .tag-main-second {
background-color: rgb(235, 15, 228);
}
.footer .badge .tag-main-third {
background-color: rgb(10, 207, 39);
}
.footer .badge .tag-main-fourth {
background-color: rgb(229, 131, 12);
}
</style> </style>

210
src/components/blogs/ceshi.vue

@ -1,189 +1,45 @@
<template> <template>
<div> <div>
<div <div v-for="blog in bloglist" :key="blog.id">
v-for="anchor in titles" <!-- 在这里展示你的博客内容 -->
:style="{ padding: `10px 0 10px ${anchor.indent}px` }" <h2>{{ blog.blogtitle }}</h2>
@click="handleAnchorClick(anchor)" <p>{{ blog.blogcontent }}</p>
:key="anchor.lineIndex"
>
<a style="cursor: pointer">{{ anchor.title }}</a>
</div> </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> </div>
</template> </template>
<script setup lang="ts"> <script lang="ts" setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import type { blogInterface } from '@/api/admin';
const text = ` import { get } from '@/tools/request';
# heading 1 const current = ref(1);
contentcontentcontent const total = ref();
contentcontentcontent const pageSize = ref(5);
contentcontentcontent const bloglist = ref<blogInterface[]>([])
contentcontentcontentcontentcontentcontent const dataLoaded = ref(false);
contentcontentcontent const fetchData = async (page: number, pageSize: number) => {
contentcontentcontentcontentcontentcontent try {
contentcontentcontent const response = await get('/blogs/list', {
contentcontentcontentcontentcontentcontent page,
contentcontentcontent page_size: pageSize,
contentcontentcontentcontentcontentcontent });
contentcontentcontent bloglist.value = response.data.data.blogs;
contentcontentcontentcontentcontentcontent total.value = response.data.data.total;
contentcontentcontent } catch (error) {
contentcontentcontentcontentcontentcontent console.error('Failed to fetch data', error);
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;
} }
};
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) => ({ onMounted(() => {
title: el.innerText, fetchData(current.value, pageSize.value);
lineIndex: el.getAttribute('data-v-md-line') || '', //
indent: 20 * (parseInt(el.tagName.substring(1)) - 1) //
}));
}); });
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> </script>

27
src/views/blog/blogcontent/BlogDetailView.vue

@ -1,14 +1,17 @@
<template> <template>
<div id="blogDetail"> <div id="blogDetail">
<div v-for="anchor in titles" :style="{ padding: `4px 0 4px ${anchor.indent * 20}px` }" <!-- <div v-for="anchor in titles" :style="{ padding: `4px 0 4px ${anchor.indent * 20}px` }"
@click="handleAnchorClick(anchor)" :key="anchor.lineIndex"> @click="handleAnchorClick(anchor)" :key="anchor.lineIndex">
<a style="cursor: pointer">{{ anchor.title }}</a> <a style="cursor: pointer">{{ anchor.title }}</a>
</div> </div> -->
<a-card>
<v-md-preview v-if="text.blogcontent" :text="text.blogcontent" v-bind="previewProps" /> <v-md-preview v-if="text.blogcontent" :text="text.blogcontent" v-bind="previewProps" />
</a-card>
</div> </div>
</template>
<script setup lang="ts"> </template>
<script setup lang="ts">
import { ref, onMounted, nextTick } from 'vue'; import { ref, onMounted, nextTick } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { get } from '@/tools/request'; import { get } from '@/tools/request';
@ -18,6 +21,10 @@ const text = ref({
blogtitle: "", blogtitle: "",
blogcontent: "" blogcontent: ""
}); });
const titles = ref<{ title: string; lineIndex: string; indent: number }[]>([]); const titles = ref<{ title: string; lineIndex: string; indent: number }[]>([]);
// Props for v-md-preview component // Props for v-md-preview component
@ -41,7 +48,7 @@ const blogOneList = async () => {
const processHeadings = async () => { const processHeadings = async () => {
await nextTick(); await nextTick();
const anchors = document.querySelectorAll('#blogDetail h1, #blogDetail h2, #blogDetail h3, #blogDetail h4, #blogDetail h5, #blogDetail h6'); const anchors = document.querySelectorAll('#blogDetail h1, #blogDetail h2, #blogDetail h3, #blogDetail h4, #blogDetail h5, #blogDetail h6');
const titlesArray = Array.from(anchors).filter((title:any) => !!title.innerText.trim()); const titlesArray = Array.from(anchors).filter((title: any) => !!title.innerText.trim());
if (!titlesArray.length) { if (!titlesArray.length) {
titles.value = []; titles.value = [];
@ -85,9 +92,9 @@ onMounted(async () => {
</script> </script>
<style scoped> <style scoped>
#blogDetail { #blogDetail {
width: 45%; width: 45%;
} margin: 0 24px;
</style> }
</style>

68
src/views/blog/blogcontent/BlogListView.vue

@ -48,6 +48,16 @@
</a-card> </a-card>
</a-badge-ribbon> </a-badge-ribbon>
</div> </div>
<div id="pagination">
<a-pagination v-model:current="current" v-if="dataLoaded" v-model:page-size="pageSizeRef"
:page-size-options="pageSizeOptions" :total="total" show-size-changer @change="onShowSizeChange">
<template #buildOptionText="props">
<span v-if="props.value !== '50'">{{ props.value }}/</span>
<span v-else>全部</span>
</template>
</a-pagination>
</div>
</div> </div>
</template> </template>
@ -56,45 +66,49 @@ import { onMounted, ref } from 'vue';
import iconComponents from '@/assets'; import iconComponents from '@/assets';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import type { blogInterface } from '@/api/admin'; import type { blogInterface } from '@/api/admin';
import {get} from "@/tools/request" import { get } from "@/tools/request"
import router from '@/router'; import router from '@/router';
const randomColor = () => { const randomColor = () => {
const labelColor = ref(["processing", "success", "error", "warning", "magenta", "red", "volcano", "orange", "gold", "lime", "green", "cyan", "blue", "geekblue", "purple"]) const labelColor = ref(["processing", "success", "error", "warning", "magenta", "red", "volcano", "orange", "gold", "lime", "green", "cyan", "blue", "geekblue", "purple"])
return labelColor.value[Math.floor(Math.random() * labelColor.value.length)]; return labelColor.value[Math.floor(Math.random() * labelColor.value.length)];
} }
const dataLoaded = ref(false);
//
const pageSizeOptions = ref<string[]>(['10', '20', '30', '40', '50']);
const current = ref(1);
const total = ref();
const pageSizeRef = ref(10);
const bloglist = ref<blogInterface[]>([]) const bloglist = ref<blogInterface[]>([])
const blogList = async () => { const onShowSizeChange = (page: number) => {
current.value = page;
blogList(page, pageSizeRef.value)
};
const blogList = async (page: number, pageSize: number) => {
try { try {
const response = await get("/blogs/list"); const response = await get('/blogs/list', {
if (response) { page,
bloglist.value = response.data.data.map((items: any, index: any) => ({ page_size: pageSize,
key: (index + 1).toString(), });
id: items.id, console.log(response)
blogtitle: items.blogtitle, bloglist.value = response.data.data.blogs;
create_at: dayjs(items.create_at).format('YYYY-MM-DD HH:mm:ss'), total.value = response.data.data.total; //
update_at: dayjs(items.update_at).format('YYYY-MM-DD HH:mm:ss'), pageSizeRef.value = pageSize; // response.data.data.page_size
readnum: items.readnum, dataLoaded.value = true
readminite: (items.blogcontent.length/150).toFixed(2),
wordcount: items.blogcontent.length,
img: items.img,
blogcontent: items.blogcontent,
typename: items.typename,
labelnames: items.labelnames
}))
} else {
console.log("bloglist is not exits")
}
} catch (error) { } catch (error) {
console.log("bloglist is error") console.error('Failed to fetch data', error);
} }
};
} const readMore = (id: any) => {
const readMore=(id:any)=>{
router.push(`/blog/${id}`) router.push(`/blog/${id}`)
} }
onMounted(() => { onMounted(() => {
blogList(); blogList(current.value, pageSizeRef.value);
}); });
</script> </script>
@ -192,4 +206,8 @@ onMounted(() => {
margin-left: 24px; margin-left: 24px;
} }
#pagination{
display: flex;
justify-content: right;
}
</style> </style>
|||||||
100:0
Loading…
Cancel
Save