191 lines
3.3 KiB
Vue
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>
|