docs_vue2/components/OneFooter.vue
2022-06-14 09:05:00 +08:00

191 lines
3.3 KiB
Vue

<template>
<footer class="one-footer">
<p class="copyright"></p>
</footer>
</template>
<script>
import { compact, find, findIndex } from "lodash";
import i18n from "../common/i18n";
export default {
name: "one-footer",
mixins: [i18n],
props: {
nav: {
type: Array,
default() {
return [];
},
},
},
data() {
return {
year: new Date().getFullYear(),
};
},
computed: {
links() {
let segments = compact(this.canonicalPath.split("/"));
return getLinks(this.nav, segments);
},
level() {
return this.links ? this.links.level : 0;
},
base() {
return this.links ? this.links.base : null;
},
prev() {
return this.resolve(this.links ? this.links.prev : null);
},
next() {
return this.resolve(this.links ? this.links.next : null);
},
single() {
return (!this.prev && !this.next) || this.level < 1;
},
},
watch: {
single: {
handler(val) {
this.$emit("update", {
hasLinks: !val,
});
},
immediate: true,
},
},
methods: {
resolve(link) {
let { slug, title, link: lk } = link || {};
if (typeof slug !== "string" || lk === false) {
return null;
}
let base = this.base;
return {
title,
to: this.getLocalePath(slug ? `${base}/${slug}` : base),
};
},
},
};
function findSibling(items, start, forward) {
if ((start === 0 && !forward) || (start === items.length - 1 && forward)) {
return null;
}
let candidates = forward
? items.slice(start + 1)
: items.slice(0, start).reverse();
return find(candidates, ({ disabled }) => !disabled);
}
function getLinks(nav, remaining, level = 0, base = "") {
let [segment = "", ...segments] = [...remaining];
let i = findIndex(nav, ({ slug }) => slug === segment);
if (i === -1) {
return null;
}
let links = {
prev: findSibling(nav, i, false),
next: findSibling(nav, i, true),
level,
base,
};
let sub = nav[i].children;
if (!sub) {
if (segments.length) {
return null;
}
return links;
}
return (
getLinks(sub, segments, level + 1, segment ? `${base}/${segment}` : base) ||
links
);
}
</script>
<style lang="stylus" scoped>
arrow() {
content: '';
display: block;
width: 23px;
height: 33px;
background: #333 url('/icons/angle.svg') no-repeat 50% 50% / auto 21.5px;
transition: background-color 0.3s;
}
.one-footer {
clear: both;
padding: 0 60px;
}
.links {
border-top: 1px solid #eee;
padding: 20px 0 80px;
overflow: hidden;
}
.empty {
display: none;
overflow: hidden;
}
.prev, .next {
display: block;
line-height: 33px;
color: #333;
text-decoration: none;
&:hover, &.focus-visible {
&::before, &::after {
background-color: #5b5b5b;
}
}
&:active {
&::before, &::after {
background-color: #818181;
}
}
}
.prev::before, .next::after {
arrow();
}
.prev {
float: left;
&::before {
float: left;
margin-right: 15px;
transform: rotate(180deg);
}
}
.next {
float: right;
&::after {
float: right;
margin-left: 15px;
}
}
.copyright {
margin: 0;
padding: 25px 0 20px;
border-top: 1px solid #eee;
line-height: 1;
font-size: 12px;
text-align: center;
}
</style>