添加文章主页
This commit is contained in:
@@ -1 +0,0 @@
|
||||
请在左侧的文章目录选择内容。
|
87
src/components/ContentIndex.vue
Normal file
87
src/components/ContentIndex.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="content-index">
|
||||
|
||||
<router-link
|
||||
v-for="(item, index) in itemList"
|
||||
:key="index + '_' + item.itemName"
|
||||
:to="{
|
||||
name: 'Content',
|
||||
params: {
|
||||
category: item.categoryName,
|
||||
name: item.itemName,
|
||||
},
|
||||
}"
|
||||
class="index-item card"
|
||||
>
|
||||
<div class="card-content">
|
||||
<div class="info-row info-title">{{ item.itemLabel }}</div>
|
||||
<div class="info-row info-desc">
|
||||
<b-tag type="is-success" rounded>{{ item.categoryLabel }}</b-tag>
|
||||
<b-tag type="is-primary" rounded>{{ item.createdAt }}</b-tag>
|
||||
</div>
|
||||
</div>
|
||||
</router-link>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ContentIndex',
|
||||
props: {
|
||||
|
||||
/** 内容列表 */
|
||||
itemList: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.content-index {
|
||||
margin: 0 auto;
|
||||
padding: 2.5rem;
|
||||
box-sizing: border-box;
|
||||
max-width: 50rem;
|
||||
user-select: none;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.index-item {
|
||||
margin-bottom: 1.5em;
|
||||
cursor: pointer;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.info-row:not(:first-child) {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.info-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.info-desc {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.tag:not(:first-child) {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
@@ -125,7 +125,6 @@ export default {
|
||||
margin: 0 auto;
|
||||
padding: 2.5rem;
|
||||
box-sizing: border-box;
|
||||
min-width: 12.5rem;
|
||||
max-width: 60rem;
|
||||
user-select: text;
|
||||
|
||||
|
@@ -61,12 +61,26 @@
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="content-wrapper">
|
||||
<markdown-parser :md-src="contentData" />
|
||||
<b-loading
|
||||
:active="isLoading"
|
||||
:can-cancel="false"
|
||||
:is-full-page="false"
|
||||
></b-loading>
|
||||
|
||||
<!-- 文章主页 -->
|
||||
<template v-if="isIndex">
|
||||
<content-index
|
||||
:item-list="contentListAll"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- 文章内容页 -->
|
||||
<template v-else>
|
||||
<markdown-parser
|
||||
:md-src="contentData"
|
||||
/>
|
||||
<b-loading
|
||||
:active="isLoading"
|
||||
:can-cancel="false"
|
||||
:is-full-page="false"
|
||||
/>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -76,16 +90,21 @@
|
||||
import { setTitle, toast } from '@/assets/js/utils';
|
||||
import { getContentFile } from '@/request/index';
|
||||
|
||||
import ContentIndex from '@/components/ContentIndex';
|
||||
import MarkdownParser from '@/components/MarkdownParser';
|
||||
|
||||
export default {
|
||||
name: 'ContentView',
|
||||
components: {
|
||||
ContentIndex,
|
||||
MarkdownParser,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
/** 是否为文章主页 */
|
||||
isIndex: false,
|
||||
|
||||
/** 是否正在载入内容 */
|
||||
isLoading: false,
|
||||
|
||||
@@ -105,20 +124,21 @@ export default {
|
||||
},
|
||||
|
||||
/** 内容列表 */
|
||||
contentList: [
|
||||
{
|
||||
name: '_index',
|
||||
label: '索引页面',
|
||||
isHide: true,
|
||||
items: [{
|
||||
name: 'contents',
|
||||
title: '文章页面',
|
||||
createdAt: '',
|
||||
updatedAt: '',
|
||||
}],
|
||||
isExpanded: false,
|
||||
},
|
||||
],
|
||||
contentList: [{
|
||||
name: '',
|
||||
label: '',
|
||||
items: [{
|
||||
name: '',
|
||||
title: '',
|
||||
createdAt: '',
|
||||
updatedAt: '',
|
||||
}],
|
||||
isHide: true,
|
||||
isExpanded: false,
|
||||
}],
|
||||
|
||||
/** 内容列表(全部) */
|
||||
contentListAll: [],
|
||||
|
||||
}
|
||||
},
|
||||
@@ -152,6 +172,7 @@ export default {
|
||||
});
|
||||
|
||||
this.contentList = listCurr;
|
||||
this.initContentListAll();
|
||||
|
||||
} else {
|
||||
toast({
|
||||
@@ -166,12 +187,54 @@ export default {
|
||||
|
||||
},
|
||||
|
||||
/** 初始化内容列表 */
|
||||
initContentListAll() {
|
||||
|
||||
const src = this.contentList;
|
||||
|
||||
/** @type {{ createdAt: string }[]} */
|
||||
const result = [];
|
||||
|
||||
src.forEach((category) => {
|
||||
|
||||
if (category.isHide) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
name: categoryName,
|
||||
label: categoryLabel,
|
||||
} = category;
|
||||
|
||||
category.items.forEach((item) => {
|
||||
item['categoryName'] = categoryName;
|
||||
item['categoryLabel'] = categoryLabel;
|
||||
item['itemName'] = item.name;
|
||||
item['itemLabel'] = item.title;
|
||||
result.push(item);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
result.sort((a, b) => {
|
||||
|
||||
const dateA = (a.createdAt || '');
|
||||
const dateB = (b.createdAt || '');
|
||||
|
||||
return dateB.localeCompare(dateA, 'co');
|
||||
|
||||
});
|
||||
|
||||
this.contentListAll = result;
|
||||
|
||||
},
|
||||
|
||||
/** 切换页面 */
|
||||
changePage(category, itemName) {
|
||||
changePage(categoryName, itemName) {
|
||||
this.$router.push({
|
||||
name: 'Content',
|
||||
params: {
|
||||
category: category,
|
||||
category: categoryName,
|
||||
name: itemName,
|
||||
}
|
||||
});
|
||||
@@ -241,18 +304,21 @@ export default {
|
||||
params: routeParams,
|
||||
} = this.$route;
|
||||
|
||||
if (routeName === 'Content') {
|
||||
const isContentPage = (routeName === 'Content');
|
||||
|
||||
if (isContentPage) {
|
||||
this.getContentFile({
|
||||
category: routeParams.category,
|
||||
itemName: routeParams.name,
|
||||
});
|
||||
} else {
|
||||
this.getContentFile({
|
||||
category: '_index',
|
||||
itemName: 'contents',
|
||||
this.updateContentInfo({
|
||||
isIndex: true,
|
||||
});
|
||||
}
|
||||
|
||||
this.isIndex = !isContentPage;
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -260,6 +326,7 @@ export default {
|
||||
* @param {object} options
|
||||
* @param {string} options.category 分类名称
|
||||
* @param {string} options.itemName 内容名称
|
||||
* @param {boolean} [options.isIndex] 是否为文章主页
|
||||
*/
|
||||
updateContentInfo(options) {
|
||||
|
||||
@@ -268,15 +335,29 @@ export default {
|
||||
const {
|
||||
category,
|
||||
itemName,
|
||||
isIndex = false,
|
||||
} = options;
|
||||
|
||||
const { contentInfo, contentList } = this;
|
||||
|
||||
if (isIndex) {
|
||||
setTitle('文章');
|
||||
contentInfo.category = 'index';
|
||||
contentInfo.createdAt = '2022-03-01';
|
||||
contentInfo.updatedAt = '2022-03-05';
|
||||
contentInfo.itemName = 'index';
|
||||
contentInfo.itemtitle = '文章';
|
||||
contentList.forEach((item) => {
|
||||
item.isExpanded = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(category && itemName)) {
|
||||
console.error('更新内容信息失败!');
|
||||
return;
|
||||
}
|
||||
|
||||
const { contentInfo, contentList } = this;
|
||||
|
||||
const categoryInfo = contentList.find((item) => {
|
||||
return (item.name === category);
|
||||
});
|
||||
@@ -294,12 +375,12 @@ export default {
|
||||
});
|
||||
|
||||
if (itemInfo) {
|
||||
setTitle(itemInfo.title);
|
||||
contentInfo.category = category;
|
||||
contentInfo.createdAt = (itemInfo.createdAt || '无');
|
||||
contentInfo.updatedAt = (itemInfo.updatedAt || '无');
|
||||
contentInfo.itemName = (itemInfo.name || '');
|
||||
contentInfo.itemtitle = (itemInfo.title || '无标题');
|
||||
setTitle(itemInfo.title);
|
||||
} else {
|
||||
console.error('获取内容信息失败!');
|
||||
}
|
||||
|
Reference in New Issue
Block a user