优化交互,开放文档支持目录导航

This commit is contained in:
暮光:城中城
2021-12-06 23:03:56 +08:00
parent 189e96ff42
commit 1c747054bb
39 changed files with 7870 additions and 870 deletions

View File

@@ -1,34 +1,70 @@
<template>
<div v-if="apiDoc.shareInstruction">
<div class="markdown-body" v-html="markdownToHtml(apiDoc.shareInstruction)" style="margin: 0 auto;max-width: 1000px;"></div>
<a-row>
<a-col :xs="0" :sm="4" :md="4" :lg="6" :xl="6" v-if="navigationList.length > 0">
<Navigation ref="navigationRef" :heading="navigationList"></Navigation>
</a-col>
<a-col :xs="24" :sm="navigationList.length > 0?20:24" :md="navigationList.length > 0?20:24" :lg="navigationList.length > 0?18:24" :xl="navigationList.length > 0?18:24">
<div class="markdown-body share-instruction" v-html="markdownToHtml(apiDoc.shareInstruction)" style="margin: 0 auto;max-width: 1000px;"></div>
</a-col>
</a-row>
</div>
<div v-else style="text-align: center;">欢迎访问开放API文档</div>
</template>
<script>
import {toRefs, ref, reactive, onMounted, watch, computed} from 'vue';
import { useRouter, useRoute } from "vue-router";
import {computed, onMounted, ref, watch} from 'vue';
import {useStore} from 'vuex';
import { message } from 'ant-design-vue';
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
import {markdownIt} from 'mavon-editor'
import 'mavon-editor/dist/markdown/github-markdown.min.css'
import 'mavon-editor/dist/css/index.css'
import swaggerAnalysis from "../../assets/core/SwaggerAnalysis";
import Navigation from './components/Navigation.vue'
export default {
components: {Navigation},
setup() {
const store = useStore();
const apiDoc = computed(() => store.state.apiDoc);
onMounted(() => {
let navigationRef = ref();
watch(store.getters.getApiDoc, () => {
setTimeout(() => {
createNavigationHeading('.share-instruction');
}, 100);
});
const markdownToHtml = desc => {
return markdownIt.render(desc || '');
}
let navigationList = ref([]);
const createNavigationHeading = (domClass) => {
if (!document.querySelector(domClass)) {
return [];
}
let headNodeArr = document.querySelector(domClass).querySelectorAll('h1,h2,h3,h4,h5,h6');
if (headNodeArr.length <= 0) {
return [];
}
let headArr = [];
headNodeArr.forEach(node => {
let text = node.innerHTML.replace(/^\s+/g, '').replace(/\s+$/g, '').replace(/<\/?[^>]+(>|$)/g, '');
headArr.push({
node: node,
level: parseInt(node.tagName.replace(/[h]/i, ''), 10),
text: text
});
});
navigationList.value = headArr;
};
onMounted(() => {
});
return {
apiDoc,
navigationRef,
navigationList,
markdownToHtml,
};
},
};
</script>
<style>
.share-instruction{padding: 0 10px;}
</style>

View File

@@ -0,0 +1,106 @@
<template>
<div class="navigation">
<div ref="navigationRef" style="display: inline-block;width: 100%;height: 1px;"></div>
<div class="navigation-heading" :style="{width: navigationWidth}">
<div v-for="item in heading" :class="'heading-item heading-'+item.level" @click="headingItemClick(item)">
{{item.text}}
</div>
</div>
</div>
</template>
<script>
import {computed, onMounted, ref, watch} from 'vue';
import {useStore} from 'vuex';
export default {
props: {
heading: {
type: Array,
default: []
},
},
setup(props) {
const store = useStore();
let navigationWidth = ref('100px');
onMounted(() => {
window.onresize = () => {
computeNavigationWidth();
}
setTimeout(() => {
computeNavigationWidth();
}, 100);
});
watch(store.getters.getLeftAsideWidth, () => {
computeNavigationWidth();
});
let navigationRef = ref();
const computeNavigationWidth = () => {
navigationWidth.value = window.getComputedStyle(navigationRef.value, null).width;
};
// 滚动到指定节点
const headingItemClick = (item) => {
item.node.scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"});
};
return {
navigationRef,
navigationWidth,
headingItemClick,
};
},
};
</script>
<style>
.navigation {
width: 100%;
}
.navigation-heading {
position: fixed;
z-index: 4;
top: 150px;
height: calc(100vh - 250px);
width: 100%;
overflow-y: auto;
padding-left: 16px;
box-sizing: border-box;
}
.navigation-heading .heading-item {
padding: 5px 0;
cursor: pointer;
color: #646a73;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.navigation-heading .heading-item:hover {
color: #3370ff;
}
.navigation-heading .heading-1 {
padding-left: 0;
}
.navigation-heading .heading-2 {
padding-left: 16px;
}
.navigation-heading .heading-3 {
padding-left: 32px;
}
.navigation-heading .heading-4 {
padding-left: 48px;
}
.navigation-heading .heading-5 {
padding-left: 64px;
}
.navigation-heading .heading-6 {
padding-left: 80px;
}
</style>