添加文章主页
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;
|
margin: 0 auto;
|
||||||
padding: 2.5rem;
|
padding: 2.5rem;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
min-width: 12.5rem;
|
|
||||||
max-width: 60rem;
|
max-width: 60rem;
|
||||||
user-select: text;
|
user-select: text;
|
||||||
|
|
||||||
|
@@ -61,12 +61,26 @@
|
|||||||
|
|
||||||
<!-- 内容区域 -->
|
<!-- 内容区域 -->
|
||||||
<div class="content-wrapper">
|
<div class="content-wrapper">
|
||||||
<markdown-parser :md-src="contentData" />
|
|
||||||
<b-loading
|
<!-- 文章主页 -->
|
||||||
:active="isLoading"
|
<template v-if="isIndex">
|
||||||
:can-cancel="false"
|
<content-index
|
||||||
:is-full-page="false"
|
:item-list="contentListAll"
|
||||||
></b-loading>
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 文章内容页 -->
|
||||||
|
<template v-else>
|
||||||
|
<markdown-parser
|
||||||
|
:md-src="contentData"
|
||||||
|
/>
|
||||||
|
<b-loading
|
||||||
|
:active="isLoading"
|
||||||
|
:can-cancel="false"
|
||||||
|
:is-full-page="false"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -76,16 +90,21 @@
|
|||||||
import { setTitle, toast } from '@/assets/js/utils';
|
import { setTitle, toast } from '@/assets/js/utils';
|
||||||
import { getContentFile } from '@/request/index';
|
import { getContentFile } from '@/request/index';
|
||||||
|
|
||||||
|
import ContentIndex from '@/components/ContentIndex';
|
||||||
import MarkdownParser from '@/components/MarkdownParser';
|
import MarkdownParser from '@/components/MarkdownParser';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ContentView',
|
name: 'ContentView',
|
||||||
components: {
|
components: {
|
||||||
|
ContentIndex,
|
||||||
MarkdownParser,
|
MarkdownParser,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
||||||
|
/** 是否为文章主页 */
|
||||||
|
isIndex: false,
|
||||||
|
|
||||||
/** 是否正在载入内容 */
|
/** 是否正在载入内容 */
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
|
|
||||||
@@ -105,20 +124,21 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/** 内容列表 */
|
/** 内容列表 */
|
||||||
contentList: [
|
contentList: [{
|
||||||
{
|
name: '',
|
||||||
name: '_index',
|
label: '',
|
||||||
label: '索引页面',
|
items: [{
|
||||||
isHide: true,
|
name: '',
|
||||||
items: [{
|
title: '',
|
||||||
name: 'contents',
|
createdAt: '',
|
||||||
title: '文章页面',
|
updatedAt: '',
|
||||||
createdAt: '',
|
}],
|
||||||
updatedAt: '',
|
isHide: true,
|
||||||
}],
|
isExpanded: false,
|
||||||
isExpanded: false,
|
}],
|
||||||
},
|
|
||||||
],
|
/** 内容列表(全部) */
|
||||||
|
contentListAll: [],
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -152,6 +172,7 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.contentList = listCurr;
|
this.contentList = listCurr;
|
||||||
|
this.initContentListAll();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
toast({
|
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({
|
this.$router.push({
|
||||||
name: 'Content',
|
name: 'Content',
|
||||||
params: {
|
params: {
|
||||||
category: category,
|
category: categoryName,
|
||||||
name: itemName,
|
name: itemName,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -241,18 +304,21 @@ export default {
|
|||||||
params: routeParams,
|
params: routeParams,
|
||||||
} = this.$route;
|
} = this.$route;
|
||||||
|
|
||||||
if (routeName === 'Content') {
|
const isContentPage = (routeName === 'Content');
|
||||||
|
|
||||||
|
if (isContentPage) {
|
||||||
this.getContentFile({
|
this.getContentFile({
|
||||||
category: routeParams.category,
|
category: routeParams.category,
|
||||||
itemName: routeParams.name,
|
itemName: routeParams.name,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.getContentFile({
|
this.updateContentInfo({
|
||||||
category: '_index',
|
isIndex: true,
|
||||||
itemName: 'contents',
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isIndex = !isContentPage;
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -260,6 +326,7 @@ export default {
|
|||||||
* @param {object} options
|
* @param {object} options
|
||||||
* @param {string} options.category 分类名称
|
* @param {string} options.category 分类名称
|
||||||
* @param {string} options.itemName 内容名称
|
* @param {string} options.itemName 内容名称
|
||||||
|
* @param {boolean} [options.isIndex] 是否为文章主页
|
||||||
*/
|
*/
|
||||||
updateContentInfo(options) {
|
updateContentInfo(options) {
|
||||||
|
|
||||||
@@ -268,15 +335,29 @@ export default {
|
|||||||
const {
|
const {
|
||||||
category,
|
category,
|
||||||
itemName,
|
itemName,
|
||||||
|
isIndex = false,
|
||||||
} = options;
|
} = 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)) {
|
if (!(category && itemName)) {
|
||||||
console.error('更新内容信息失败!');
|
console.error('更新内容信息失败!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { contentInfo, contentList } = this;
|
|
||||||
|
|
||||||
const categoryInfo = contentList.find((item) => {
|
const categoryInfo = contentList.find((item) => {
|
||||||
return (item.name === category);
|
return (item.name === category);
|
||||||
});
|
});
|
||||||
@@ -294,12 +375,12 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (itemInfo) {
|
if (itemInfo) {
|
||||||
|
setTitle(itemInfo.title);
|
||||||
contentInfo.category = category;
|
contentInfo.category = category;
|
||||||
contentInfo.createdAt = (itemInfo.createdAt || '无');
|
contentInfo.createdAt = (itemInfo.createdAt || '无');
|
||||||
contentInfo.updatedAt = (itemInfo.updatedAt || '无');
|
contentInfo.updatedAt = (itemInfo.updatedAt || '无');
|
||||||
contentInfo.itemName = (itemInfo.name || '');
|
contentInfo.itemName = (itemInfo.name || '');
|
||||||
contentInfo.itemtitle = (itemInfo.title || '无标题');
|
contentInfo.itemtitle = (itemInfo.title || '无标题');
|
||||||
setTitle(itemInfo.title);
|
|
||||||
} else {
|
} else {
|
||||||
console.error('获取内容信息失败!');
|
console.error('获取内容信息失败!');
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user